xref: /openbmc/linux/drivers/acpi/acpica/dsutils.c (revision 597473720f4dc69749542bfcfed4a927a43d935e)
1*95857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
295b482a8SLen Brown /*******************************************************************************
395b482a8SLen Brown  *
495b482a8SLen Brown  * Module Name: dsutils - Dispatcher utilities
595b482a8SLen Brown  *
695b482a8SLen Brown  ******************************************************************************/
795b482a8SLen Brown 
895b482a8SLen Brown #include <acpi/acpi.h>
9e2f7a777SLen Brown #include "accommon.h"
10e2f7a777SLen Brown #include "acparser.h"
11e2f7a777SLen Brown #include "amlcode.h"
12e2f7a777SLen Brown #include "acdispat.h"
13e2f7a777SLen Brown #include "acinterp.h"
14e2f7a777SLen Brown #include "acnamesp.h"
15e2f7a777SLen Brown #include "acdebug.h"
1695b482a8SLen Brown 
1795b482a8SLen Brown #define _COMPONENT          ACPI_DISPATCHER
1895b482a8SLen Brown ACPI_MODULE_NAME("dsutils")
1995b482a8SLen Brown 
2095b482a8SLen Brown /*******************************************************************************
2195b482a8SLen Brown  *
2295b482a8SLen Brown  * FUNCTION:    acpi_ds_clear_implicit_return
2395b482a8SLen Brown  *
2495b482a8SLen Brown  * PARAMETERS:  walk_state          - Current State
2595b482a8SLen Brown  *
2695b482a8SLen Brown  * RETURN:      None.
2795b482a8SLen Brown  *
2895b482a8SLen Brown  * DESCRIPTION: Clear and remove a reference on an implicit return value. Used
2995b482a8SLen Brown  *              to delete "stale" return values (if enabled, the return value
3095b482a8SLen Brown  *              from every operator is saved at least momentarily, in case the
3195b482a8SLen Brown  *              parent method exits.)
3295b482a8SLen Brown  *
3395b482a8SLen Brown  ******************************************************************************/
acpi_ds_clear_implicit_return(struct acpi_walk_state * walk_state)3495b482a8SLen Brown void acpi_ds_clear_implicit_return(struct acpi_walk_state *walk_state)
3595b482a8SLen Brown {
3695b482a8SLen Brown 	ACPI_FUNCTION_NAME(ds_clear_implicit_return);
3795b482a8SLen Brown 
3895b482a8SLen Brown 	/*
3995b482a8SLen Brown 	 * Slack must be enabled for this feature
4095b482a8SLen Brown 	 */
4195b482a8SLen Brown 	if (!acpi_gbl_enable_interpreter_slack) {
4295b482a8SLen Brown 		return;
4395b482a8SLen Brown 	}
4495b482a8SLen Brown 
4595b482a8SLen Brown 	if (walk_state->implicit_return_obj) {
4695b482a8SLen Brown 		/*
4795b482a8SLen Brown 		 * Delete any "stale" implicit return. However, in
4895b482a8SLen Brown 		 * complex statements, the implicit return value can be
4995b482a8SLen Brown 		 * bubbled up several levels.
5095b482a8SLen Brown 		 */
5195b482a8SLen Brown 		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
5295b482a8SLen Brown 				  "Removing reference on stale implicit return obj %p\n",
5395b482a8SLen Brown 				  walk_state->implicit_return_obj));
5495b482a8SLen Brown 
5595b482a8SLen Brown 		acpi_ut_remove_reference(walk_state->implicit_return_obj);
5695b482a8SLen Brown 		walk_state->implicit_return_obj = NULL;
5795b482a8SLen Brown 	}
5895b482a8SLen Brown }
5995b482a8SLen Brown 
6095b482a8SLen Brown /*******************************************************************************
6195b482a8SLen Brown  *
6295b482a8SLen Brown  * FUNCTION:    acpi_ds_do_implicit_return
6395b482a8SLen Brown  *
6495b482a8SLen Brown  * PARAMETERS:  return_desc         - The return value
6595b482a8SLen Brown  *              walk_state          - Current State
6695b482a8SLen Brown  *              add_reference       - True if a reference should be added to the
6795b482a8SLen Brown  *                                    return object
6895b482a8SLen Brown  *
6995b482a8SLen Brown  * RETURN:      TRUE if implicit return enabled, FALSE otherwise
7095b482a8SLen Brown  *
7195b482a8SLen Brown  * DESCRIPTION: Implements the optional "implicit return".  We save the result
7295b482a8SLen Brown  *              of every ASL operator and control method invocation in case the
7395b482a8SLen Brown  *              parent method exit. Before storing a new return value, we
7495b482a8SLen Brown  *              delete the previous return value.
7595b482a8SLen Brown  *
7695b482a8SLen Brown  ******************************************************************************/
7795b482a8SLen Brown 
7895b482a8SLen Brown u8
acpi_ds_do_implicit_return(union acpi_operand_object * return_desc,struct acpi_walk_state * walk_state,u8 add_reference)7995b482a8SLen Brown acpi_ds_do_implicit_return(union acpi_operand_object *return_desc,
8095b482a8SLen Brown 			   struct acpi_walk_state *walk_state, u8 add_reference)
8195b482a8SLen Brown {
8295b482a8SLen Brown 	ACPI_FUNCTION_NAME(ds_do_implicit_return);
8395b482a8SLen Brown 
8495b482a8SLen Brown 	/*
8595b482a8SLen Brown 	 * Slack must be enabled for this feature, and we must
8695b482a8SLen Brown 	 * have a valid return object
8795b482a8SLen Brown 	 */
8895b482a8SLen Brown 	if ((!acpi_gbl_enable_interpreter_slack) || (!return_desc)) {
8995b482a8SLen Brown 		return (FALSE);
9095b482a8SLen Brown 	}
9195b482a8SLen Brown 
9295b482a8SLen Brown 	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
9395b482a8SLen Brown 			  "Result %p will be implicitly returned; Prev=%p\n",
9495b482a8SLen Brown 			  return_desc, walk_state->implicit_return_obj));
9595b482a8SLen Brown 
9695b482a8SLen Brown 	/*
9795b482a8SLen Brown 	 * Delete any "stale" implicit return value first. However, in
9895b482a8SLen Brown 	 * complex statements, the implicit return value can be
9995b482a8SLen Brown 	 * bubbled up several levels, so we don't clear the value if it
10095b482a8SLen Brown 	 * is the same as the return_desc.
10195b482a8SLen Brown 	 */
10295b482a8SLen Brown 	if (walk_state->implicit_return_obj) {
10395b482a8SLen Brown 		if (walk_state->implicit_return_obj == return_desc) {
10495b482a8SLen Brown 			return (TRUE);
10595b482a8SLen Brown 		}
10695b482a8SLen Brown 		acpi_ds_clear_implicit_return(walk_state);
10795b482a8SLen Brown 	}
10895b482a8SLen Brown 
10995b482a8SLen Brown 	/* Save the implicit return value, add a reference if requested */
11095b482a8SLen Brown 
11195b482a8SLen Brown 	walk_state->implicit_return_obj = return_desc;
11295b482a8SLen Brown 	if (add_reference) {
11395b482a8SLen Brown 		acpi_ut_add_reference(return_desc);
11495b482a8SLen Brown 	}
11595b482a8SLen Brown 
11695b482a8SLen Brown 	return (TRUE);
11795b482a8SLen Brown }
11895b482a8SLen Brown 
11995b482a8SLen Brown /*******************************************************************************
12095b482a8SLen Brown  *
12195b482a8SLen Brown  * FUNCTION:    acpi_ds_is_result_used
12295b482a8SLen Brown  *
123ba494beeSBob Moore  * PARAMETERS:  op                  - Current Op
12495b482a8SLen Brown  *              walk_state          - Current State
12595b482a8SLen Brown  *
12695b482a8SLen Brown  * RETURN:      TRUE if result is used, FALSE otherwise
12795b482a8SLen Brown  *
12895b482a8SLen Brown  * DESCRIPTION: Check if a result object will be used by the parent
12995b482a8SLen Brown  *
13095b482a8SLen Brown  ******************************************************************************/
13195b482a8SLen Brown 
13295b482a8SLen Brown u8
acpi_ds_is_result_used(union acpi_parse_object * op,struct acpi_walk_state * walk_state)13395b482a8SLen Brown acpi_ds_is_result_used(union acpi_parse_object * op,
13495b482a8SLen Brown 		       struct acpi_walk_state * walk_state)
13595b482a8SLen Brown {
13695b482a8SLen Brown 	const struct acpi_opcode_info *parent_info;
13795b482a8SLen Brown 
13895b482a8SLen Brown 	ACPI_FUNCTION_TRACE_PTR(ds_is_result_used, op);
13995b482a8SLen Brown 
14095b482a8SLen Brown 	/* Must have both an Op and a Result Object */
14195b482a8SLen Brown 
14295b482a8SLen Brown 	if (!op) {
14395b482a8SLen Brown 		ACPI_ERROR((AE_INFO, "Null Op"));
144fd1af712SBob Moore 		return_UINT8(TRUE);
14595b482a8SLen Brown 	}
14695b482a8SLen Brown 
14795b482a8SLen Brown 	/*
14895b482a8SLen Brown 	 * We know that this operator is not a
14995b482a8SLen Brown 	 * Return() operator (would not come here.) The following code is the
15095b482a8SLen Brown 	 * optional support for a so-called "implicit return". Some AML code
15195b482a8SLen Brown 	 * assumes that the last value of the method is "implicitly" returned
15295b482a8SLen Brown 	 * to the caller. Just save the last result as the return value.
15395b482a8SLen Brown 	 * NOTE: this is optional because the ASL language does not actually
15495b482a8SLen Brown 	 * support this behavior.
15595b482a8SLen Brown 	 */
15695b482a8SLen Brown 	(void)acpi_ds_do_implicit_return(walk_state->result_obj, walk_state,
15795b482a8SLen Brown 					 TRUE);
15895b482a8SLen Brown 
15995b482a8SLen Brown 	/*
16095b482a8SLen Brown 	 * Now determine if the parent will use the result
16195b482a8SLen Brown 	 *
16295b482a8SLen Brown 	 * If there is no parent, or the parent is a scope_op, we are executing
16395b482a8SLen Brown 	 * at the method level. An executing method typically has no parent,
16495b482a8SLen Brown 	 * since each method is parsed separately. A method invoked externally
16595b482a8SLen Brown 	 * via execute_control_method has a scope_op as the parent.
16695b482a8SLen Brown 	 */
16795b482a8SLen Brown 	if ((!op->common.parent) ||
16895b482a8SLen Brown 	    (op->common.parent->common.aml_opcode == AML_SCOPE_OP)) {
16995b482a8SLen Brown 
17095b482a8SLen Brown 		/* No parent, the return value cannot possibly be used */
17195b482a8SLen Brown 
17295b482a8SLen Brown 		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
17395b482a8SLen Brown 				  "At Method level, result of [%s] not used\n",
17495b482a8SLen Brown 				  acpi_ps_get_opcode_name(op->common.
17595b482a8SLen Brown 							  aml_opcode)));
176fd1af712SBob Moore 		return_UINT8(FALSE);
17795b482a8SLen Brown 	}
17895b482a8SLen Brown 
17995b482a8SLen Brown 	/* Get info on the parent. The root_op is AML_SCOPE */
18095b482a8SLen Brown 
18195b482a8SLen Brown 	parent_info =
18295b482a8SLen Brown 	    acpi_ps_get_opcode_info(op->common.parent->common.aml_opcode);
18395b482a8SLen Brown 	if (parent_info->class == AML_CLASS_UNKNOWN) {
18495b482a8SLen Brown 		ACPI_ERROR((AE_INFO, "Unknown parent opcode Op=%p", op));
185fd1af712SBob Moore 		return_UINT8(FALSE);
18695b482a8SLen Brown 	}
18795b482a8SLen Brown 
18895b482a8SLen Brown 	/*
18995b482a8SLen Brown 	 * Decide what to do with the result based on the parent. If
19095b482a8SLen Brown 	 * the parent opcode will not use the result, delete the object.
19195b482a8SLen Brown 	 * Otherwise leave it as is, it will be deleted when it is used
19295b482a8SLen Brown 	 * as an operand later.
19395b482a8SLen Brown 	 */
19495b482a8SLen Brown 	switch (parent_info->class) {
19595b482a8SLen Brown 	case AML_CLASS_CONTROL:
19695b482a8SLen Brown 
19795b482a8SLen Brown 		switch (op->common.parent->common.aml_opcode) {
19895b482a8SLen Brown 		case AML_RETURN_OP:
19995b482a8SLen Brown 
20095b482a8SLen Brown 			/* Never delete the return value associated with a return opcode */
20195b482a8SLen Brown 
20295b482a8SLen Brown 			goto result_used;
20395b482a8SLen Brown 
20495b482a8SLen Brown 		case AML_IF_OP:
20595b482a8SLen Brown 		case AML_WHILE_OP:
20695b482a8SLen Brown 			/*
20795b482a8SLen Brown 			 * If we are executing the predicate AND this is the predicate op,
20895b482a8SLen Brown 			 * we will use the return value
20995b482a8SLen Brown 			 */
21095b482a8SLen Brown 			if ((walk_state->control_state->common.state ==
2111fad8738SBob Moore 			     ACPI_CONTROL_PREDICATE_EXECUTING) &&
2121fad8738SBob Moore 			    (walk_state->control_state->control.predicate_op ==
2131fad8738SBob Moore 			     op)) {
21495b482a8SLen Brown 				goto result_used;
21595b482a8SLen Brown 			}
21695b482a8SLen Brown 			break;
21795b482a8SLen Brown 
21895b482a8SLen Brown 		default:
2191d1ea1b7SChao Guan 
22095b482a8SLen Brown 			/* Ignore other control opcodes */
2211d1ea1b7SChao Guan 
22295b482a8SLen Brown 			break;
22395b482a8SLen Brown 		}
22495b482a8SLen Brown 
22595b482a8SLen Brown 		/* The general control opcode returns no result */
22695b482a8SLen Brown 
22795b482a8SLen Brown 		goto result_not_used;
22895b482a8SLen Brown 
22995b482a8SLen Brown 	case AML_CLASS_CREATE:
23095b482a8SLen Brown 		/*
23195b482a8SLen Brown 		 * These opcodes allow term_arg(s) as operands and therefore
23295b482a8SLen Brown 		 * the operands can be method calls. The result is used.
23395b482a8SLen Brown 		 */
23495b482a8SLen Brown 		goto result_used;
23595b482a8SLen Brown 
23695b482a8SLen Brown 	case AML_CLASS_NAMED_OBJECT:
23795b482a8SLen Brown 
23895b482a8SLen Brown 		if ((op->common.parent->common.aml_opcode == AML_REGION_OP) ||
23995b482a8SLen Brown 		    (op->common.parent->common.aml_opcode == AML_DATA_REGION_OP)
24095b482a8SLen Brown 		    || (op->common.parent->common.aml_opcode == AML_PACKAGE_OP)
24195b482a8SLen Brown 		    || (op->common.parent->common.aml_opcode == AML_BUFFER_OP)
24295b482a8SLen Brown 		    || (op->common.parent->common.aml_opcode ==
2439ff5a21aSBob Moore 			AML_VARIABLE_PACKAGE_OP)
2449ff5a21aSBob Moore 		    || (op->common.parent->common.aml_opcode ==
24595b482a8SLen Brown 			AML_INT_EVAL_SUBTREE_OP)
24695b482a8SLen Brown 		    || (op->common.parent->common.aml_opcode ==
24795b482a8SLen Brown 			AML_BANK_FIELD_OP)) {
24895b482a8SLen Brown 			/*
24995b482a8SLen Brown 			 * These opcodes allow term_arg(s) as operands and therefore
25095b482a8SLen Brown 			 * the operands can be method calls. The result is used.
25195b482a8SLen Brown 			 */
25295b482a8SLen Brown 			goto result_used;
25395b482a8SLen Brown 		}
25495b482a8SLen Brown 
25595b482a8SLen Brown 		goto result_not_used;
25695b482a8SLen Brown 
25795b482a8SLen Brown 	default:
25895b482a8SLen Brown 		/*
25995b482a8SLen Brown 		 * In all other cases. the parent will actually use the return
26095b482a8SLen Brown 		 * object, so keep it.
26195b482a8SLen Brown 		 */
26295b482a8SLen Brown 		goto result_used;
26395b482a8SLen Brown 	}
26495b482a8SLen Brown 
26595b482a8SLen Brown result_used:
26695b482a8SLen Brown 	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
26795b482a8SLen Brown 			  "Result of [%s] used by Parent [%s] Op=%p\n",
26895b482a8SLen Brown 			  acpi_ps_get_opcode_name(op->common.aml_opcode),
26995b482a8SLen Brown 			  acpi_ps_get_opcode_name(op->common.parent->common.
27095b482a8SLen Brown 						  aml_opcode), op));
27195b482a8SLen Brown 
272fd1af712SBob Moore 	return_UINT8(TRUE);
27395b482a8SLen Brown 
27495b482a8SLen Brown result_not_used:
27595b482a8SLen Brown 	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
27695b482a8SLen Brown 			  "Result of [%s] not used by Parent [%s] Op=%p\n",
27795b482a8SLen Brown 			  acpi_ps_get_opcode_name(op->common.aml_opcode),
27895b482a8SLen Brown 			  acpi_ps_get_opcode_name(op->common.parent->common.
27995b482a8SLen Brown 						  aml_opcode), op));
28095b482a8SLen Brown 
281fd1af712SBob Moore 	return_UINT8(FALSE);
28295b482a8SLen Brown }
28395b482a8SLen Brown 
28495b482a8SLen Brown /*******************************************************************************
28595b482a8SLen Brown  *
28695b482a8SLen Brown  * FUNCTION:    acpi_ds_delete_result_if_not_used
28795b482a8SLen Brown  *
288ba494beeSBob Moore  * PARAMETERS:  op              - Current parse Op
28995b482a8SLen Brown  *              result_obj      - Result of the operation
29095b482a8SLen Brown  *              walk_state      - Current state
29195b482a8SLen Brown  *
29295b482a8SLen Brown  * RETURN:      Status
29395b482a8SLen Brown  *
29495b482a8SLen Brown  * DESCRIPTION: Used after interpretation of an opcode. If there is an internal
29595b482a8SLen Brown  *              result descriptor, check if the parent opcode will actually use
29695b482a8SLen Brown  *              this result. If not, delete the result now so that it will
29795b482a8SLen Brown  *              not become orphaned.
29895b482a8SLen Brown  *
29995b482a8SLen Brown  ******************************************************************************/
30095b482a8SLen Brown 
30195b482a8SLen Brown void
acpi_ds_delete_result_if_not_used(union acpi_parse_object * op,union acpi_operand_object * result_obj,struct acpi_walk_state * walk_state)30295b482a8SLen Brown acpi_ds_delete_result_if_not_used(union acpi_parse_object *op,
30395b482a8SLen Brown 				  union acpi_operand_object *result_obj,
30495b482a8SLen Brown 				  struct acpi_walk_state *walk_state)
30595b482a8SLen Brown {
30695b482a8SLen Brown 	union acpi_operand_object *obj_desc;
30795b482a8SLen Brown 	acpi_status status;
30895b482a8SLen Brown 
30995b482a8SLen Brown 	ACPI_FUNCTION_TRACE_PTR(ds_delete_result_if_not_used, result_obj);
31095b482a8SLen Brown 
31195b482a8SLen Brown 	if (!op) {
31295b482a8SLen Brown 		ACPI_ERROR((AE_INFO, "Null Op"));
31395b482a8SLen Brown 		return_VOID;
31495b482a8SLen Brown 	}
31595b482a8SLen Brown 
31695b482a8SLen Brown 	if (!result_obj) {
31795b482a8SLen Brown 		return_VOID;
31895b482a8SLen Brown 	}
31995b482a8SLen Brown 
32095b482a8SLen Brown 	if (!acpi_ds_is_result_used(op, walk_state)) {
32195b482a8SLen Brown 
32295b482a8SLen Brown 		/* Must pop the result stack (obj_desc should be equal to result_obj) */
32395b482a8SLen Brown 
32495b482a8SLen Brown 		status = acpi_ds_result_pop(&obj_desc, walk_state);
32595b482a8SLen Brown 		if (ACPI_SUCCESS(status)) {
32695b482a8SLen Brown 			acpi_ut_remove_reference(result_obj);
32795b482a8SLen Brown 		}
32895b482a8SLen Brown 	}
32995b482a8SLen Brown 
33095b482a8SLen Brown 	return_VOID;
33195b482a8SLen Brown }
33295b482a8SLen Brown 
33395b482a8SLen Brown /*******************************************************************************
33495b482a8SLen Brown  *
33595b482a8SLen Brown  * FUNCTION:    acpi_ds_resolve_operands
33695b482a8SLen Brown  *
33795b482a8SLen Brown  * PARAMETERS:  walk_state          - Current walk state with operands on stack
33895b482a8SLen Brown  *
33995b482a8SLen Brown  * RETURN:      Status
34095b482a8SLen Brown  *
34195b482a8SLen Brown  * DESCRIPTION: Resolve all operands to their values. Used to prepare
34295b482a8SLen Brown  *              arguments to a control method invocation (a call from one
34395b482a8SLen Brown  *              method to another.)
34495b482a8SLen Brown  *
34595b482a8SLen Brown  ******************************************************************************/
34695b482a8SLen Brown 
acpi_ds_resolve_operands(struct acpi_walk_state * walk_state)34795b482a8SLen Brown acpi_status acpi_ds_resolve_operands(struct acpi_walk_state *walk_state)
34895b482a8SLen Brown {
34995b482a8SLen Brown 	u32 i;
35095b482a8SLen Brown 	acpi_status status = AE_OK;
35195b482a8SLen Brown 
35295b482a8SLen Brown 	ACPI_FUNCTION_TRACE_PTR(ds_resolve_operands, walk_state);
35395b482a8SLen Brown 
35495b482a8SLen Brown 	/*
35595b482a8SLen Brown 	 * Attempt to resolve each of the valid operands
35695b482a8SLen Brown 	 * Method arguments are passed by reference, not by value. This means
35795b482a8SLen Brown 	 * that the actual objects are passed, not copies of the objects.
35895b482a8SLen Brown 	 */
35995b482a8SLen Brown 	for (i = 0; i < walk_state->num_operands; i++) {
36095b482a8SLen Brown 		status =
36195b482a8SLen Brown 		    acpi_ex_resolve_to_value(&walk_state->operands[i],
36295b482a8SLen Brown 					     walk_state);
36395b482a8SLen Brown 		if (ACPI_FAILURE(status)) {
36495b482a8SLen Brown 			break;
36595b482a8SLen Brown 		}
36695b482a8SLen Brown 	}
36795b482a8SLen Brown 
36895b482a8SLen Brown 	return_ACPI_STATUS(status);
36995b482a8SLen Brown }
37095b482a8SLen Brown 
37195b482a8SLen Brown /*******************************************************************************
37295b482a8SLen Brown  *
37395b482a8SLen Brown  * FUNCTION:    acpi_ds_clear_operands
37495b482a8SLen Brown  *
37595b482a8SLen Brown  * PARAMETERS:  walk_state          - Current walk state with operands on stack
37695b482a8SLen Brown  *
37795b482a8SLen Brown  * RETURN:      None
37895b482a8SLen Brown  *
37995b482a8SLen Brown  * DESCRIPTION: Clear all operands on the current walk state operand stack.
38095b482a8SLen Brown  *
38195b482a8SLen Brown  ******************************************************************************/
38295b482a8SLen Brown 
acpi_ds_clear_operands(struct acpi_walk_state * walk_state)38395b482a8SLen Brown void acpi_ds_clear_operands(struct acpi_walk_state *walk_state)
38495b482a8SLen Brown {
38595b482a8SLen Brown 	u32 i;
38695b482a8SLen Brown 
38795b482a8SLen Brown 	ACPI_FUNCTION_TRACE_PTR(ds_clear_operands, walk_state);
38895b482a8SLen Brown 
38995b482a8SLen Brown 	/* Remove a reference on each operand on the stack */
39095b482a8SLen Brown 
39195b482a8SLen Brown 	for (i = 0; i < walk_state->num_operands; i++) {
39295b482a8SLen Brown 		/*
39395b482a8SLen Brown 		 * Remove a reference to all operands, including both
39495b482a8SLen Brown 		 * "Arguments" and "Targets".
39595b482a8SLen Brown 		 */
39695b482a8SLen Brown 		acpi_ut_remove_reference(walk_state->operands[i]);
39795b482a8SLen Brown 		walk_state->operands[i] = NULL;
39895b482a8SLen Brown 	}
39995b482a8SLen Brown 
40095b482a8SLen Brown 	walk_state->num_operands = 0;
40195b482a8SLen Brown 	return_VOID;
40295b482a8SLen Brown }
40395b482a8SLen Brown 
40495b482a8SLen Brown /*******************************************************************************
40595b482a8SLen Brown  *
40695b482a8SLen Brown  * FUNCTION:    acpi_ds_create_operand
40795b482a8SLen Brown  *
40895b482a8SLen Brown  * PARAMETERS:  walk_state      - Current walk state
409ba494beeSBob Moore  *              arg             - Parse object for the argument
41095b482a8SLen Brown  *              arg_index       - Which argument (zero based)
41195b482a8SLen Brown  *
41295b482a8SLen Brown  * RETURN:      Status
41395b482a8SLen Brown  *
41495b482a8SLen Brown  * DESCRIPTION: Translate a parse tree object that is an argument to an AML
41595b482a8SLen Brown  *              opcode to the equivalent interpreter object. This may include
41695b482a8SLen Brown  *              looking up a name or entering a new name into the internal
41795b482a8SLen Brown  *              namespace.
41895b482a8SLen Brown  *
41995b482a8SLen Brown  ******************************************************************************/
42095b482a8SLen Brown 
42195b482a8SLen Brown acpi_status
acpi_ds_create_operand(struct acpi_walk_state * walk_state,union acpi_parse_object * arg,u32 arg_index)42295b482a8SLen Brown acpi_ds_create_operand(struct acpi_walk_state *walk_state,
42395b482a8SLen Brown 		       union acpi_parse_object *arg, u32 arg_index)
42495b482a8SLen Brown {
42595b482a8SLen Brown 	acpi_status status = AE_OK;
42695b482a8SLen Brown 	char *name_string;
42795b482a8SLen Brown 	u32 name_length;
42895b482a8SLen Brown 	union acpi_operand_object *obj_desc;
42995b482a8SLen Brown 	union acpi_parse_object *parent_op;
43095b482a8SLen Brown 	u16 opcode;
43195b482a8SLen Brown 	acpi_interpreter_mode interpreter_mode;
43295b482a8SLen Brown 	const struct acpi_opcode_info *op_info;
43395b482a8SLen Brown 
43495b482a8SLen Brown 	ACPI_FUNCTION_TRACE_PTR(ds_create_operand, arg);
43595b482a8SLen Brown 
43695b482a8SLen Brown 	/* A valid name must be looked up in the namespace */
43795b482a8SLen Brown 
43895b482a8SLen Brown 	if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) &&
43995b482a8SLen Brown 	    (arg->common.value.string) &&
44095b482a8SLen Brown 	    !(arg->common.flags & ACPI_PARSEOP_IN_STACK)) {
44195b482a8SLen Brown 		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n",
44295b482a8SLen Brown 				  arg));
44395b482a8SLen Brown 
44495b482a8SLen Brown 		/* Get the entire name string from the AML stream */
44595b482a8SLen Brown 
4461fad8738SBob Moore 		status = acpi_ex_get_name_string(ACPI_TYPE_ANY,
44795b482a8SLen Brown 						 arg->common.value.buffer,
44895b482a8SLen Brown 						 &name_string, &name_length);
44995b482a8SLen Brown 
45095b482a8SLen Brown 		if (ACPI_FAILURE(status)) {
45195b482a8SLen Brown 			return_ACPI_STATUS(status);
45295b482a8SLen Brown 		}
45395b482a8SLen Brown 
45495b482a8SLen Brown 		/* All prefixes have been handled, and the name is in name_string */
45595b482a8SLen Brown 
45695b482a8SLen Brown 		/*
45795b482a8SLen Brown 		 * Special handling for buffer_field declarations. This is a deferred
45895b482a8SLen Brown 		 * opcode that unfortunately defines the field name as the last
45995b482a8SLen Brown 		 * parameter instead of the first. We get here when we are performing
46095b482a8SLen Brown 		 * the deferred execution, so the actual name of the field is already
46195b482a8SLen Brown 		 * in the namespace. We don't want to attempt to look it up again
46295b482a8SLen Brown 		 * because we may be executing in a different scope than where the
46395b482a8SLen Brown 		 * actual opcode exists.
46495b482a8SLen Brown 		 */
46595b482a8SLen Brown 		if ((walk_state->deferred_node) &&
46695b482a8SLen Brown 		    (walk_state->deferred_node->type == ACPI_TYPE_BUFFER_FIELD)
4671fad8738SBob Moore 		    && (arg_index == (u32)
4681fad8738SBob Moore 			((walk_state->opcode == AML_CREATE_FIELD_OP) ? 3 : 2))) {
46995b482a8SLen Brown 			obj_desc =
47095b482a8SLen Brown 			    ACPI_CAST_PTR(union acpi_operand_object,
47195b482a8SLen Brown 					  walk_state->deferred_node);
47295b482a8SLen Brown 			status = AE_OK;
47395b482a8SLen Brown 		} else {	/* All other opcodes */
47495b482a8SLen Brown 
47595b482a8SLen Brown 			/*
47695b482a8SLen Brown 			 * Differentiate between a namespace "create" operation
47795b482a8SLen Brown 			 * versus a "lookup" operation (IMODE_LOAD_PASS2 vs.
47895b482a8SLen Brown 			 * IMODE_EXECUTE) in order to support the creation of
47995b482a8SLen Brown 			 * namespace objects during the execution of control methods.
48095b482a8SLen Brown 			 */
48195b482a8SLen Brown 			parent_op = arg->common.parent;
48295b482a8SLen Brown 			op_info =
48395b482a8SLen Brown 			    acpi_ps_get_opcode_info(parent_op->common.
48495b482a8SLen Brown 						    aml_opcode);
4851fad8738SBob Moore 
4861fad8738SBob Moore 			if ((op_info->flags & AML_NSNODE) &&
4871fad8738SBob Moore 			    (parent_op->common.aml_opcode !=
48895b482a8SLen Brown 			     AML_INT_METHODCALL_OP)
48995b482a8SLen Brown 			    && (parent_op->common.aml_opcode != AML_REGION_OP)
49095b482a8SLen Brown 			    && (parent_op->common.aml_opcode !=
49195b482a8SLen Brown 				AML_INT_NAMEPATH_OP)) {
49295b482a8SLen Brown 
49395b482a8SLen Brown 				/* Enter name into namespace if not found */
49495b482a8SLen Brown 
49595b482a8SLen Brown 				interpreter_mode = ACPI_IMODE_LOAD_PASS2;
49695b482a8SLen Brown 			} else {
49795b482a8SLen Brown 				/* Return a failure if name not found */
49895b482a8SLen Brown 
49995b482a8SLen Brown 				interpreter_mode = ACPI_IMODE_EXECUTE;
50095b482a8SLen Brown 			}
50195b482a8SLen Brown 
50295b482a8SLen Brown 			status =
50395b482a8SLen Brown 			    acpi_ns_lookup(walk_state->scope_info, name_string,
50495b482a8SLen Brown 					   ACPI_TYPE_ANY, interpreter_mode,
50595b482a8SLen Brown 					   ACPI_NS_SEARCH_PARENT |
50695b482a8SLen Brown 					   ACPI_NS_DONT_OPEN_SCOPE, walk_state,
50795b482a8SLen Brown 					   ACPI_CAST_INDIRECT_PTR(struct
50895b482a8SLen Brown 								  acpi_namespace_node,
50995b482a8SLen Brown 								  &obj_desc));
51095b482a8SLen Brown 			/*
51195b482a8SLen Brown 			 * The only case where we pass through (ignore) a NOT_FOUND
51295b482a8SLen Brown 			 * error is for the cond_ref_of opcode.
51395b482a8SLen Brown 			 */
51495b482a8SLen Brown 			if (status == AE_NOT_FOUND) {
51595b482a8SLen Brown 				if (parent_op->common.aml_opcode ==
5169ff5a21aSBob Moore 				    AML_CONDITIONAL_REF_OF_OP) {
51795b482a8SLen Brown 					/*
51895b482a8SLen Brown 					 * For the Conditional Reference op, it's OK if
51995b482a8SLen Brown 					 * the name is not found;  We just need a way to
52095b482a8SLen Brown 					 * indicate this to the interpreter, set the
52195b482a8SLen Brown 					 * object to the root
52295b482a8SLen Brown 					 */
5231f86e8c1SLv Zheng 					obj_desc =
5241f86e8c1SLv Zheng 					    ACPI_CAST_PTR(union
52595b482a8SLen Brown 								 acpi_operand_object,
52695b482a8SLen Brown 								 acpi_gbl_root_node);
52795b482a8SLen Brown 					status = AE_OK;
52856a3d5e7SBob Moore 				} else if (parent_op->common.aml_opcode ==
52956a3d5e7SBob Moore 					   AML_EXTERNAL_OP) {
5307fdb5ceaSBob Moore 					/*
5317fdb5ceaSBob Moore 					 * This opcode should never appear here. It is used only
5327fdb5ceaSBob Moore 					 * by AML disassemblers and is surrounded by an If(0)
5337fdb5ceaSBob Moore 					 * by the ASL compiler.
5347fdb5ceaSBob Moore 					 *
5357fdb5ceaSBob Moore 					 * Therefore, if we see it here, it is a serious error.
5367fdb5ceaSBob Moore 					 */
5377fdb5ceaSBob Moore 					status = AE_AML_BAD_OPCODE;
53895b482a8SLen Brown 				} else {
53995b482a8SLen Brown 					/*
54095b482a8SLen Brown 					 * We just plain didn't find it -- which is a
54195b482a8SLen Brown 					 * very serious error at this point
54295b482a8SLen Brown 					 */
54395b482a8SLen Brown 					status = AE_AML_NAME_NOT_FOUND;
54495b482a8SLen Brown 				}
54595b482a8SLen Brown 			}
54695b482a8SLen Brown 
54795b482a8SLen Brown 			if (ACPI_FAILURE(status)) {
54816ccf829SBob Moore 				ACPI_ERROR_NAMESPACE(walk_state->scope_info,
54916ccf829SBob Moore 						     name_string, status);
55095b482a8SLen Brown 			}
55195b482a8SLen Brown 		}
55295b482a8SLen Brown 
55395b482a8SLen Brown 		/* Free the namestring created above */
55495b482a8SLen Brown 
55595b482a8SLen Brown 		ACPI_FREE(name_string);
55695b482a8SLen Brown 
55795b482a8SLen Brown 		/* Check status from the lookup */
55895b482a8SLen Brown 
55995b482a8SLen Brown 		if (ACPI_FAILURE(status)) {
56095b482a8SLen Brown 			return_ACPI_STATUS(status);
56195b482a8SLen Brown 		}
56295b482a8SLen Brown 
56395b482a8SLen Brown 		/* Put the resulting object onto the current object stack */
56495b482a8SLen Brown 
56595b482a8SLen Brown 		status = acpi_ds_obj_stack_push(obj_desc, walk_state);
56695b482a8SLen Brown 		if (ACPI_FAILURE(status)) {
56795b482a8SLen Brown 			return_ACPI_STATUS(status);
56895b482a8SLen Brown 		}
5698a2a2501SLv Zheng 
5708a2a2501SLv Zheng 		acpi_db_display_argument_object(obj_desc, walk_state);
57195b482a8SLen Brown 	} else {
57295b482a8SLen Brown 		/* Check for null name case */
57395b482a8SLen Brown 
57495b482a8SLen Brown 		if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) &&
57595b482a8SLen Brown 		    !(arg->common.flags & ACPI_PARSEOP_IN_STACK)) {
57695b482a8SLen Brown 			/*
57795b482a8SLen Brown 			 * If the name is null, this means that this is an
57895b482a8SLen Brown 			 * optional result parameter that was not specified
57995b482a8SLen Brown 			 * in the original ASL. Create a Zero Constant for a
58095b482a8SLen Brown 			 * placeholder. (Store to a constant is a Noop.)
58195b482a8SLen Brown 			 */
58295b482a8SLen Brown 			opcode = AML_ZERO_OP;	/* Has no arguments! */
58395b482a8SLen Brown 
58495b482a8SLen Brown 			ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
58595b482a8SLen Brown 					  "Null namepath: Arg=%p\n", arg));
58695b482a8SLen Brown 		} else {
58795b482a8SLen Brown 			opcode = arg->common.aml_opcode;
58895b482a8SLen Brown 		}
58995b482a8SLen Brown 
59095b482a8SLen Brown 		/* Get the object type of the argument */
59195b482a8SLen Brown 
59295b482a8SLen Brown 		op_info = acpi_ps_get_opcode_info(opcode);
59395b482a8SLen Brown 		if (op_info->object_type == ACPI_TYPE_INVALID) {
59495b482a8SLen Brown 			return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
59595b482a8SLen Brown 		}
59695b482a8SLen Brown 
5971fad8738SBob Moore 		if ((op_info->flags & AML_HAS_RETVAL) ||
5981fad8738SBob Moore 		    (arg->common.flags & ACPI_PARSEOP_IN_STACK)) {
59995b482a8SLen Brown 			/*
60095b482a8SLen Brown 			 * Use value that was already previously returned
60195b482a8SLen Brown 			 * by the evaluation of this argument
60295b482a8SLen Brown 			 */
60395b482a8SLen Brown 			status = acpi_ds_result_pop(&obj_desc, walk_state);
60495b482a8SLen Brown 			if (ACPI_FAILURE(status)) {
60595b482a8SLen Brown 				/*
60695b482a8SLen Brown 				 * Only error is underflow, and this indicates
60795b482a8SLen Brown 				 * a missing or null operand!
60895b482a8SLen Brown 				 */
60995b482a8SLen Brown 				ACPI_EXCEPTION((AE_INFO, status,
61095b482a8SLen Brown 						"Missing or null operand"));
61195b482a8SLen Brown 				return_ACPI_STATUS(status);
61295b482a8SLen Brown 			}
61395b482a8SLen Brown 		} else {
61495b482a8SLen Brown 			/* Create an ACPI_INTERNAL_OBJECT for the argument */
61595b482a8SLen Brown 
61695b482a8SLen Brown 			obj_desc =
61795b482a8SLen Brown 			    acpi_ut_create_internal_object(op_info->
61895b482a8SLen Brown 							   object_type);
61995b482a8SLen Brown 			if (!obj_desc) {
62095b482a8SLen Brown 				return_ACPI_STATUS(AE_NO_MEMORY);
62195b482a8SLen Brown 			}
62295b482a8SLen Brown 
62395b482a8SLen Brown 			/* Initialize the new object */
62495b482a8SLen Brown 
62595b482a8SLen Brown 			status =
62695b482a8SLen Brown 			    acpi_ds_init_object_from_op(walk_state, arg, opcode,
62795b482a8SLen Brown 							&obj_desc);
62895b482a8SLen Brown 			if (ACPI_FAILURE(status)) {
62995b482a8SLen Brown 				acpi_ut_delete_object_desc(obj_desc);
63095b482a8SLen Brown 				return_ACPI_STATUS(status);
63195b482a8SLen Brown 			}
63295b482a8SLen Brown 		}
63395b482a8SLen Brown 
63495b482a8SLen Brown 		/* Put the operand object on the object stack */
63595b482a8SLen Brown 
63695b482a8SLen Brown 		status = acpi_ds_obj_stack_push(obj_desc, walk_state);
63795b482a8SLen Brown 		if (ACPI_FAILURE(status)) {
63895b482a8SLen Brown 			return_ACPI_STATUS(status);
63995b482a8SLen Brown 		}
64095b482a8SLen Brown 
6418a2a2501SLv Zheng 		acpi_db_display_argument_object(obj_desc, walk_state);
64295b482a8SLen Brown 	}
64395b482a8SLen Brown 
64495b482a8SLen Brown 	return_ACPI_STATUS(AE_OK);
64595b482a8SLen Brown }
64695b482a8SLen Brown 
64795b482a8SLen Brown /*******************************************************************************
64895b482a8SLen Brown  *
64995b482a8SLen Brown  * FUNCTION:    acpi_ds_create_operands
65095b482a8SLen Brown  *
65195b482a8SLen Brown  * PARAMETERS:  walk_state          - Current state
65295b482a8SLen Brown  *              first_arg           - First argument of a parser argument tree
65395b482a8SLen Brown  *
65495b482a8SLen Brown  * RETURN:      Status
65595b482a8SLen Brown  *
65695b482a8SLen Brown  * DESCRIPTION: Convert an operator's arguments from a parse tree format to
65795b482a8SLen Brown  *              namespace objects and place those argument object on the object
65895b482a8SLen Brown  *              stack in preparation for evaluation by the interpreter.
65995b482a8SLen Brown  *
66095b482a8SLen Brown  ******************************************************************************/
66195b482a8SLen Brown 
66295b482a8SLen Brown acpi_status
acpi_ds_create_operands(struct acpi_walk_state * walk_state,union acpi_parse_object * first_arg)66395b482a8SLen Brown acpi_ds_create_operands(struct acpi_walk_state *walk_state,
66495b482a8SLen Brown 			union acpi_parse_object *first_arg)
66595b482a8SLen Brown {
66695b482a8SLen Brown 	acpi_status status = AE_OK;
66795b482a8SLen Brown 	union acpi_parse_object *arg;
66895b482a8SLen Brown 	union acpi_parse_object *arguments[ACPI_OBJ_NUM_OPERANDS];
66995b482a8SLen Brown 	u32 arg_count = 0;
67095b482a8SLen Brown 	u32 index = walk_state->num_operands;
67195b482a8SLen Brown 	u32 i;
67295b482a8SLen Brown 
67395b482a8SLen Brown 	ACPI_FUNCTION_TRACE_PTR(ds_create_operands, first_arg);
67495b482a8SLen Brown 
67595b482a8SLen Brown 	/* Get all arguments in the list */
67695b482a8SLen Brown 
67795b482a8SLen Brown 	arg = first_arg;
67895b482a8SLen Brown 	while (arg) {
67995b482a8SLen Brown 		if (index >= ACPI_OBJ_NUM_OPERANDS) {
68095b482a8SLen Brown 			return_ACPI_STATUS(AE_BAD_DATA);
68195b482a8SLen Brown 		}
68295b482a8SLen Brown 
68395b482a8SLen Brown 		arguments[index] = arg;
68495b482a8SLen Brown 		walk_state->operands[index] = NULL;
68595b482a8SLen Brown 
68695b482a8SLen Brown 		/* Move on to next argument, if any */
68795b482a8SLen Brown 
68895b482a8SLen Brown 		arg = arg->common.next;
68995b482a8SLen Brown 		arg_count++;
69095b482a8SLen Brown 		index++;
69195b482a8SLen Brown 	}
69295b482a8SLen Brown 
69387beb7e8SBob Moore 	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
69487beb7e8SBob Moore 			  "NumOperands %d, ArgCount %d, Index %d\n",
69587beb7e8SBob Moore 			  walk_state->num_operands, arg_count, index));
69687beb7e8SBob Moore 
69787beb7e8SBob Moore 	/* Create the interpreter arguments, in reverse order */
69887beb7e8SBob Moore 
69995b482a8SLen Brown 	index--;
70095b482a8SLen Brown 	for (i = 0; i < arg_count; i++) {
70195b482a8SLen Brown 		arg = arguments[index];
70295b482a8SLen Brown 		walk_state->operand_index = (u8)index;
70395b482a8SLen Brown 
70495b482a8SLen Brown 		status = acpi_ds_create_operand(walk_state, arg, index);
70595b482a8SLen Brown 		if (ACPI_FAILURE(status)) {
70695b482a8SLen Brown 			goto cleanup;
70795b482a8SLen Brown 		}
70895b482a8SLen Brown 
70995b482a8SLen Brown 		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
71087beb7e8SBob Moore 				  "Created Arg #%u (%p) %u args total\n",
71187beb7e8SBob Moore 				  index, arg, arg_count));
71287beb7e8SBob Moore 		index--;
71395b482a8SLen Brown 	}
71495b482a8SLen Brown 
71595b482a8SLen Brown 	return_ACPI_STATUS(status);
71695b482a8SLen Brown 
71795b482a8SLen Brown cleanup:
71895b482a8SLen Brown 	/*
71995b482a8SLen Brown 	 * We must undo everything done above; meaning that we must
72095b482a8SLen Brown 	 * pop everything off of the operand stack and delete those
72195b482a8SLen Brown 	 * objects
72295b482a8SLen Brown 	 */
72395b482a8SLen Brown 	acpi_ds_obj_stack_pop_and_delete(arg_count, walk_state);
72495b482a8SLen Brown 
725b27d6597SBob Moore 	ACPI_EXCEPTION((AE_INFO, status, "While creating Arg %u", index));
72695b482a8SLen Brown 	return_ACPI_STATUS(status);
72795b482a8SLen Brown }
72895b482a8SLen Brown 
72995b482a8SLen Brown /*****************************************************************************
73095b482a8SLen Brown  *
73195b482a8SLen Brown  * FUNCTION:    acpi_ds_evaluate_name_path
73295b482a8SLen Brown  *
73395b482a8SLen Brown  * PARAMETERS:  walk_state      - Current state of the parse tree walk,
73495b482a8SLen Brown  *                                the opcode of current operation should be
73595b482a8SLen Brown  *                                AML_INT_NAMEPATH_OP
73695b482a8SLen Brown  *
73795b482a8SLen Brown  * RETURN:      Status
73895b482a8SLen Brown  *
73995b482a8SLen Brown  * DESCRIPTION: Translate the -name_path- parse tree object to the equivalent
74095b482a8SLen Brown  *              interpreter object, convert it to value, if needed, duplicate
74195b482a8SLen Brown  *              it, if needed, and push it onto the current result stack.
74295b482a8SLen Brown  *
74395b482a8SLen Brown  ****************************************************************************/
74495b482a8SLen Brown 
acpi_ds_evaluate_name_path(struct acpi_walk_state * walk_state)74595b482a8SLen Brown acpi_status acpi_ds_evaluate_name_path(struct acpi_walk_state *walk_state)
74695b482a8SLen Brown {
74795b482a8SLen Brown 	acpi_status status = AE_OK;
74895b482a8SLen Brown 	union acpi_parse_object *op = walk_state->op;
74995b482a8SLen Brown 	union acpi_operand_object **operand = &walk_state->operands[0];
75095b482a8SLen Brown 	union acpi_operand_object *new_obj_desc;
75195b482a8SLen Brown 	u8 type;
75295b482a8SLen Brown 
75395b482a8SLen Brown 	ACPI_FUNCTION_TRACE_PTR(ds_evaluate_name_path, walk_state);
75495b482a8SLen Brown 
75595b482a8SLen Brown 	if (!op->common.parent) {
75695b482a8SLen Brown 
75795b482a8SLen Brown 		/* This happens after certain exception processing */
75895b482a8SLen Brown 
75995b482a8SLen Brown 		goto exit;
76095b482a8SLen Brown 	}
76195b482a8SLen Brown 
76295b482a8SLen Brown 	if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) ||
7639ff5a21aSBob Moore 	    (op->common.parent->common.aml_opcode == AML_VARIABLE_PACKAGE_OP) ||
76495b482a8SLen Brown 	    (op->common.parent->common.aml_opcode == AML_REF_OF_OP)) {
76595b482a8SLen Brown 
76695b482a8SLen Brown 		/* TBD: Should we specify this feature as a bit of op_info->Flags of these opcodes? */
76795b482a8SLen Brown 
76895b482a8SLen Brown 		goto exit;
76995b482a8SLen Brown 	}
77095b482a8SLen Brown 
77195b482a8SLen Brown 	status = acpi_ds_create_operand(walk_state, op, 0);
77295b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
77395b482a8SLen Brown 		goto exit;
77495b482a8SLen Brown 	}
77595b482a8SLen Brown 
77695b482a8SLen Brown 	if (op->common.flags & ACPI_PARSEOP_TARGET) {
77795b482a8SLen Brown 		new_obj_desc = *operand;
77895b482a8SLen Brown 		goto push_result;
77995b482a8SLen Brown 	}
78095b482a8SLen Brown 
7813371c19cSBob Moore 	type = (*operand)->common.type;
78295b482a8SLen Brown 
78395b482a8SLen Brown 	status = acpi_ex_resolve_to_value(operand, walk_state);
78495b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
78595b482a8SLen Brown 		goto exit;
78695b482a8SLen Brown 	}
78795b482a8SLen Brown 
78895b482a8SLen Brown 	if (type == ACPI_TYPE_INTEGER) {
78995b482a8SLen Brown 
79095b482a8SLen Brown 		/* It was incremented by acpi_ex_resolve_to_value */
79195b482a8SLen Brown 
79295b482a8SLen Brown 		acpi_ut_remove_reference(*operand);
79395b482a8SLen Brown 
79495b482a8SLen Brown 		status =
79595b482a8SLen Brown 		    acpi_ut_copy_iobject_to_iobject(*operand, &new_obj_desc,
79695b482a8SLen Brown 						    walk_state);
79795b482a8SLen Brown 		if (ACPI_FAILURE(status)) {
79895b482a8SLen Brown 			goto exit;
79995b482a8SLen Brown 		}
80095b482a8SLen Brown 	} else {
80195b482a8SLen Brown 		/*
80295b482a8SLen Brown 		 * The object either was anew created or is
80395b482a8SLen Brown 		 * a Namespace node - don't decrement it.
80495b482a8SLen Brown 		 */
80595b482a8SLen Brown 		new_obj_desc = *operand;
80695b482a8SLen Brown 	}
80795b482a8SLen Brown 
80895b482a8SLen Brown 	/* Cleanup for name-path operand */
80995b482a8SLen Brown 
81095b482a8SLen Brown 	status = acpi_ds_obj_stack_pop(1, walk_state);
81195b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
81295b482a8SLen Brown 		walk_state->result_obj = new_obj_desc;
81395b482a8SLen Brown 		goto exit;
81495b482a8SLen Brown 	}
81595b482a8SLen Brown 
81695b482a8SLen Brown push_result:
81795b482a8SLen Brown 
81895b482a8SLen Brown 	walk_state->result_obj = new_obj_desc;
81995b482a8SLen Brown 
82095b482a8SLen Brown 	status = acpi_ds_result_push(walk_state->result_obj, walk_state);
82195b482a8SLen Brown 	if (ACPI_SUCCESS(status)) {
82295b482a8SLen Brown 
82395b482a8SLen Brown 		/* Force to take it from stack */
82495b482a8SLen Brown 
82595b482a8SLen Brown 		op->common.flags |= ACPI_PARSEOP_IN_STACK;
82695b482a8SLen Brown 	}
82795b482a8SLen Brown 
82895b482a8SLen Brown exit:
82995b482a8SLen Brown 
83095b482a8SLen Brown 	return_ACPI_STATUS(status);
83195b482a8SLen Brown }
832