xref: /openbmc/linux/drivers/acpi/acpica/nsxfeval.c (revision 95b482a8d31116f3f5c2a5089569393234d06385)
1*95b482a8SLen Brown /*******************************************************************************
2*95b482a8SLen Brown  *
3*95b482a8SLen Brown  * Module Name: nsxfeval - Public interfaces to the ACPI subsystem
4*95b482a8SLen Brown  *                         ACPI Object evaluation interfaces
5*95b482a8SLen Brown  *
6*95b482a8SLen Brown  ******************************************************************************/
7*95b482a8SLen Brown 
8*95b482a8SLen Brown /*
9*95b482a8SLen Brown  * Copyright (C) 2000 - 2008, Intel Corp.
10*95b482a8SLen Brown  * All rights reserved.
11*95b482a8SLen Brown  *
12*95b482a8SLen Brown  * Redistribution and use in source and binary forms, with or without
13*95b482a8SLen Brown  * modification, are permitted provided that the following conditions
14*95b482a8SLen Brown  * are met:
15*95b482a8SLen Brown  * 1. Redistributions of source code must retain the above copyright
16*95b482a8SLen Brown  *    notice, this list of conditions, and the following disclaimer,
17*95b482a8SLen Brown  *    without modification.
18*95b482a8SLen Brown  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19*95b482a8SLen Brown  *    substantially similar to the "NO WARRANTY" disclaimer below
20*95b482a8SLen Brown  *    ("Disclaimer") and any redistribution must be conditioned upon
21*95b482a8SLen Brown  *    including a substantially similar Disclaimer requirement for further
22*95b482a8SLen Brown  *    binary redistribution.
23*95b482a8SLen Brown  * 3. Neither the names of the above-listed copyright holders nor the names
24*95b482a8SLen Brown  *    of any contributors may be used to endorse or promote products derived
25*95b482a8SLen Brown  *    from this software without specific prior written permission.
26*95b482a8SLen Brown  *
27*95b482a8SLen Brown  * Alternatively, this software may be distributed under the terms of the
28*95b482a8SLen Brown  * GNU General Public License ("GPL") version 2 as published by the Free
29*95b482a8SLen Brown  * Software Foundation.
30*95b482a8SLen Brown  *
31*95b482a8SLen Brown  * NO WARRANTY
32*95b482a8SLen Brown  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33*95b482a8SLen Brown  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34*95b482a8SLen Brown  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35*95b482a8SLen Brown  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36*95b482a8SLen Brown  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37*95b482a8SLen Brown  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38*95b482a8SLen Brown  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39*95b482a8SLen Brown  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40*95b482a8SLen Brown  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41*95b482a8SLen Brown  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42*95b482a8SLen Brown  * POSSIBILITY OF SUCH DAMAGES.
43*95b482a8SLen Brown  */
44*95b482a8SLen Brown 
45*95b482a8SLen Brown #include <acpi/acpi.h>
46*95b482a8SLen Brown #include <acpi/accommon.h>
47*95b482a8SLen Brown #include <acpi/acnamesp.h>
48*95b482a8SLen Brown #include <acpi/acinterp.h>
49*95b482a8SLen Brown 
50*95b482a8SLen Brown #define _COMPONENT          ACPI_NAMESPACE
51*95b482a8SLen Brown ACPI_MODULE_NAME("nsxfeval")
52*95b482a8SLen Brown 
53*95b482a8SLen Brown /* Local prototypes */
54*95b482a8SLen Brown static void acpi_ns_resolve_references(struct acpi_evaluate_info *info);
55*95b482a8SLen Brown 
56*95b482a8SLen Brown #ifdef ACPI_FUTURE_USAGE
57*95b482a8SLen Brown /*******************************************************************************
58*95b482a8SLen Brown  *
59*95b482a8SLen Brown  * FUNCTION:    acpi_evaluate_object_typed
60*95b482a8SLen Brown  *
61*95b482a8SLen Brown  * PARAMETERS:  Handle              - Object handle (optional)
62*95b482a8SLen Brown  *              Pathname            - Object pathname (optional)
63*95b482a8SLen Brown  *              external_params     - List of parameters to pass to method,
64*95b482a8SLen Brown  *                                    terminated by NULL.  May be NULL
65*95b482a8SLen Brown  *                                    if no parameters are being passed.
66*95b482a8SLen Brown  *              return_buffer       - Where to put method's return value (if
67*95b482a8SLen Brown  *                                    any).  If NULL, no value is returned.
68*95b482a8SLen Brown  *              return_type         - Expected type of return object
69*95b482a8SLen Brown  *
70*95b482a8SLen Brown  * RETURN:      Status
71*95b482a8SLen Brown  *
72*95b482a8SLen Brown  * DESCRIPTION: Find and evaluate the given object, passing the given
73*95b482a8SLen Brown  *              parameters if necessary.  One of "Handle" or "Pathname" must
74*95b482a8SLen Brown  *              be valid (non-null)
75*95b482a8SLen Brown  *
76*95b482a8SLen Brown  ******************************************************************************/
77*95b482a8SLen Brown 
78*95b482a8SLen Brown acpi_status
79*95b482a8SLen Brown acpi_evaluate_object_typed(acpi_handle handle,
80*95b482a8SLen Brown 			   acpi_string pathname,
81*95b482a8SLen Brown 			   struct acpi_object_list *external_params,
82*95b482a8SLen Brown 			   struct acpi_buffer *return_buffer,
83*95b482a8SLen Brown 			   acpi_object_type return_type)
84*95b482a8SLen Brown {
85*95b482a8SLen Brown 	acpi_status status;
86*95b482a8SLen Brown 	u8 must_free = FALSE;
87*95b482a8SLen Brown 
88*95b482a8SLen Brown 	ACPI_FUNCTION_TRACE(acpi_evaluate_object_typed);
89*95b482a8SLen Brown 
90*95b482a8SLen Brown 	/* Return buffer must be valid */
91*95b482a8SLen Brown 
92*95b482a8SLen Brown 	if (!return_buffer) {
93*95b482a8SLen Brown 		return_ACPI_STATUS(AE_BAD_PARAMETER);
94*95b482a8SLen Brown 	}
95*95b482a8SLen Brown 
96*95b482a8SLen Brown 	if (return_buffer->length == ACPI_ALLOCATE_BUFFER) {
97*95b482a8SLen Brown 		must_free = TRUE;
98*95b482a8SLen Brown 	}
99*95b482a8SLen Brown 
100*95b482a8SLen Brown 	/* Evaluate the object */
101*95b482a8SLen Brown 
102*95b482a8SLen Brown 	status =
103*95b482a8SLen Brown 	    acpi_evaluate_object(handle, pathname, external_params,
104*95b482a8SLen Brown 				 return_buffer);
105*95b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
106*95b482a8SLen Brown 		return_ACPI_STATUS(status);
107*95b482a8SLen Brown 	}
108*95b482a8SLen Brown 
109*95b482a8SLen Brown 	/* Type ANY means "don't care" */
110*95b482a8SLen Brown 
111*95b482a8SLen Brown 	if (return_type == ACPI_TYPE_ANY) {
112*95b482a8SLen Brown 		return_ACPI_STATUS(AE_OK);
113*95b482a8SLen Brown 	}
114*95b482a8SLen Brown 
115*95b482a8SLen Brown 	if (return_buffer->length == 0) {
116*95b482a8SLen Brown 
117*95b482a8SLen Brown 		/* Error because caller specifically asked for a return value */
118*95b482a8SLen Brown 
119*95b482a8SLen Brown 		ACPI_ERROR((AE_INFO, "No return value"));
120*95b482a8SLen Brown 		return_ACPI_STATUS(AE_NULL_OBJECT);
121*95b482a8SLen Brown 	}
122*95b482a8SLen Brown 
123*95b482a8SLen Brown 	/* Examine the object type returned from evaluate_object */
124*95b482a8SLen Brown 
125*95b482a8SLen Brown 	if (((union acpi_object *)return_buffer->pointer)->type == return_type) {
126*95b482a8SLen Brown 		return_ACPI_STATUS(AE_OK);
127*95b482a8SLen Brown 	}
128*95b482a8SLen Brown 
129*95b482a8SLen Brown 	/* Return object type does not match requested type */
130*95b482a8SLen Brown 
131*95b482a8SLen Brown 	ACPI_ERROR((AE_INFO,
132*95b482a8SLen Brown 		    "Incorrect return type [%s] requested [%s]",
133*95b482a8SLen Brown 		    acpi_ut_get_type_name(((union acpi_object *)return_buffer->
134*95b482a8SLen Brown 					   pointer)->type),
135*95b482a8SLen Brown 		    acpi_ut_get_type_name(return_type)));
136*95b482a8SLen Brown 
137*95b482a8SLen Brown 	if (must_free) {
138*95b482a8SLen Brown 
139*95b482a8SLen Brown 		/* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */
140*95b482a8SLen Brown 
141*95b482a8SLen Brown 		ACPI_FREE(return_buffer->pointer);
142*95b482a8SLen Brown 		return_buffer->pointer = NULL;
143*95b482a8SLen Brown 	}
144*95b482a8SLen Brown 
145*95b482a8SLen Brown 	return_buffer->length = 0;
146*95b482a8SLen Brown 	return_ACPI_STATUS(AE_TYPE);
147*95b482a8SLen Brown }
148*95b482a8SLen Brown 
149*95b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_evaluate_object_typed)
150*95b482a8SLen Brown #endif				/*  ACPI_FUTURE_USAGE  */
151*95b482a8SLen Brown /*******************************************************************************
152*95b482a8SLen Brown  *
153*95b482a8SLen Brown  * FUNCTION:    acpi_evaluate_object
154*95b482a8SLen Brown  *
155*95b482a8SLen Brown  * PARAMETERS:  Handle              - Object handle (optional)
156*95b482a8SLen Brown  *              Pathname            - Object pathname (optional)
157*95b482a8SLen Brown  *              external_params     - List of parameters to pass to method,
158*95b482a8SLen Brown  *                                    terminated by NULL.  May be NULL
159*95b482a8SLen Brown  *                                    if no parameters are being passed.
160*95b482a8SLen Brown  *              return_buffer       - Where to put method's return value (if
161*95b482a8SLen Brown  *                                    any).  If NULL, no value is returned.
162*95b482a8SLen Brown  *
163*95b482a8SLen Brown  * RETURN:      Status
164*95b482a8SLen Brown  *
165*95b482a8SLen Brown  * DESCRIPTION: Find and evaluate the given object, passing the given
166*95b482a8SLen Brown  *              parameters if necessary.  One of "Handle" or "Pathname" must
167*95b482a8SLen Brown  *              be valid (non-null)
168*95b482a8SLen Brown  *
169*95b482a8SLen Brown  ******************************************************************************/
170*95b482a8SLen Brown acpi_status
171*95b482a8SLen Brown acpi_evaluate_object(acpi_handle handle,
172*95b482a8SLen Brown 		     acpi_string pathname,
173*95b482a8SLen Brown 		     struct acpi_object_list *external_params,
174*95b482a8SLen Brown 		     struct acpi_buffer *return_buffer)
175*95b482a8SLen Brown {
176*95b482a8SLen Brown 	acpi_status status;
177*95b482a8SLen Brown 	struct acpi_evaluate_info *info;
178*95b482a8SLen Brown 	acpi_size buffer_space_needed;
179*95b482a8SLen Brown 	u32 i;
180*95b482a8SLen Brown 
181*95b482a8SLen Brown 	ACPI_FUNCTION_TRACE(acpi_evaluate_object);
182*95b482a8SLen Brown 
183*95b482a8SLen Brown 	/* Allocate and initialize the evaluation information block */
184*95b482a8SLen Brown 
185*95b482a8SLen Brown 	info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
186*95b482a8SLen Brown 	if (!info) {
187*95b482a8SLen Brown 		return_ACPI_STATUS(AE_NO_MEMORY);
188*95b482a8SLen Brown 	}
189*95b482a8SLen Brown 
190*95b482a8SLen Brown 	info->pathname = pathname;
191*95b482a8SLen Brown 
192*95b482a8SLen Brown 	/* Convert and validate the device handle */
193*95b482a8SLen Brown 
194*95b482a8SLen Brown 	info->prefix_node = acpi_ns_map_handle_to_node(handle);
195*95b482a8SLen Brown 	if (!info->prefix_node) {
196*95b482a8SLen Brown 		status = AE_BAD_PARAMETER;
197*95b482a8SLen Brown 		goto cleanup;
198*95b482a8SLen Brown 	}
199*95b482a8SLen Brown 
200*95b482a8SLen Brown 	/*
201*95b482a8SLen Brown 	 * If there are parameters to be passed to a control method, the external
202*95b482a8SLen Brown 	 * objects must all be converted to internal objects
203*95b482a8SLen Brown 	 */
204*95b482a8SLen Brown 	if (external_params && external_params->count) {
205*95b482a8SLen Brown 		/*
206*95b482a8SLen Brown 		 * Allocate a new parameter block for the internal objects
207*95b482a8SLen Brown 		 * Add 1 to count to allow for null terminated internal list
208*95b482a8SLen Brown 		 */
209*95b482a8SLen Brown 		info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size)
210*95b482a8SLen Brown 							 external_params->
211*95b482a8SLen Brown 							 count +
212*95b482a8SLen Brown 							 1) * sizeof(void *));
213*95b482a8SLen Brown 		if (!info->parameters) {
214*95b482a8SLen Brown 			status = AE_NO_MEMORY;
215*95b482a8SLen Brown 			goto cleanup;
216*95b482a8SLen Brown 		}
217*95b482a8SLen Brown 
218*95b482a8SLen Brown 		/* Convert each external object in the list to an internal object */
219*95b482a8SLen Brown 
220*95b482a8SLen Brown 		for (i = 0; i < external_params->count; i++) {
221*95b482a8SLen Brown 			status =
222*95b482a8SLen Brown 			    acpi_ut_copy_eobject_to_iobject(&external_params->
223*95b482a8SLen Brown 							    pointer[i],
224*95b482a8SLen Brown 							    &info->
225*95b482a8SLen Brown 							    parameters[i]);
226*95b482a8SLen Brown 			if (ACPI_FAILURE(status)) {
227*95b482a8SLen Brown 				goto cleanup;
228*95b482a8SLen Brown 			}
229*95b482a8SLen Brown 		}
230*95b482a8SLen Brown 		info->parameters[external_params->count] = NULL;
231*95b482a8SLen Brown 	}
232*95b482a8SLen Brown 
233*95b482a8SLen Brown 	/*
234*95b482a8SLen Brown 	 * Three major cases:
235*95b482a8SLen Brown 	 * 1) Fully qualified pathname
236*95b482a8SLen Brown 	 * 2) No handle, not fully qualified pathname (error)
237*95b482a8SLen Brown 	 * 3) Valid handle
238*95b482a8SLen Brown 	 */
239*95b482a8SLen Brown 	if ((pathname) && (acpi_ns_valid_root_prefix(pathname[0]))) {
240*95b482a8SLen Brown 
241*95b482a8SLen Brown 		/* The path is fully qualified, just evaluate by name */
242*95b482a8SLen Brown 
243*95b482a8SLen Brown 		info->prefix_node = NULL;
244*95b482a8SLen Brown 		status = acpi_ns_evaluate(info);
245*95b482a8SLen Brown 	} else if (!handle) {
246*95b482a8SLen Brown 		/*
247*95b482a8SLen Brown 		 * A handle is optional iff a fully qualified pathname is specified.
248*95b482a8SLen Brown 		 * Since we've already handled fully qualified names above, this is
249*95b482a8SLen Brown 		 * an error
250*95b482a8SLen Brown 		 */
251*95b482a8SLen Brown 		if (!pathname) {
252*95b482a8SLen Brown 			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
253*95b482a8SLen Brown 					  "Both Handle and Pathname are NULL"));
254*95b482a8SLen Brown 		} else {
255*95b482a8SLen Brown 			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
256*95b482a8SLen Brown 					  "Null Handle with relative pathname [%s]",
257*95b482a8SLen Brown 					  pathname));
258*95b482a8SLen Brown 		}
259*95b482a8SLen Brown 
260*95b482a8SLen Brown 		status = AE_BAD_PARAMETER;
261*95b482a8SLen Brown 	} else {
262*95b482a8SLen Brown 		/* We have a namespace a node and a possible relative path */
263*95b482a8SLen Brown 
264*95b482a8SLen Brown 		status = acpi_ns_evaluate(info);
265*95b482a8SLen Brown 	}
266*95b482a8SLen Brown 
267*95b482a8SLen Brown 	/*
268*95b482a8SLen Brown 	 * If we are expecting a return value, and all went well above,
269*95b482a8SLen Brown 	 * copy the return value to an external object.
270*95b482a8SLen Brown 	 */
271*95b482a8SLen Brown 	if (return_buffer) {
272*95b482a8SLen Brown 		if (!info->return_object) {
273*95b482a8SLen Brown 			return_buffer->length = 0;
274*95b482a8SLen Brown 		} else {
275*95b482a8SLen Brown 			if (ACPI_GET_DESCRIPTOR_TYPE(info->return_object) ==
276*95b482a8SLen Brown 			    ACPI_DESC_TYPE_NAMED) {
277*95b482a8SLen Brown 				/*
278*95b482a8SLen Brown 				 * If we received a NS Node as a return object, this means that
279*95b482a8SLen Brown 				 * the object we are evaluating has nothing interesting to
280*95b482a8SLen Brown 				 * return (such as a mutex, etc.)  We return an error because
281*95b482a8SLen Brown 				 * these types are essentially unsupported by this interface.
282*95b482a8SLen Brown 				 * We don't check up front because this makes it easier to add
283*95b482a8SLen Brown 				 * support for various types at a later date if necessary.
284*95b482a8SLen Brown 				 */
285*95b482a8SLen Brown 				status = AE_TYPE;
286*95b482a8SLen Brown 				info->return_object = NULL;	/* No need to delete a NS Node */
287*95b482a8SLen Brown 				return_buffer->length = 0;
288*95b482a8SLen Brown 			}
289*95b482a8SLen Brown 
290*95b482a8SLen Brown 			if (ACPI_SUCCESS(status)) {
291*95b482a8SLen Brown 
292*95b482a8SLen Brown 				/* Dereference Index and ref_of references */
293*95b482a8SLen Brown 
294*95b482a8SLen Brown 				acpi_ns_resolve_references(info);
295*95b482a8SLen Brown 
296*95b482a8SLen Brown 				/* Get the size of the returned object */
297*95b482a8SLen Brown 
298*95b482a8SLen Brown 				status =
299*95b482a8SLen Brown 				    acpi_ut_get_object_size(info->return_object,
300*95b482a8SLen Brown 							    &buffer_space_needed);
301*95b482a8SLen Brown 				if (ACPI_SUCCESS(status)) {
302*95b482a8SLen Brown 
303*95b482a8SLen Brown 					/* Validate/Allocate/Clear caller buffer */
304*95b482a8SLen Brown 
305*95b482a8SLen Brown 					status =
306*95b482a8SLen Brown 					    acpi_ut_initialize_buffer
307*95b482a8SLen Brown 					    (return_buffer,
308*95b482a8SLen Brown 					     buffer_space_needed);
309*95b482a8SLen Brown 					if (ACPI_FAILURE(status)) {
310*95b482a8SLen Brown 						/*
311*95b482a8SLen Brown 						 * Caller's buffer is too small or a new one can't
312*95b482a8SLen Brown 						 * be allocated
313*95b482a8SLen Brown 						 */
314*95b482a8SLen Brown 						ACPI_DEBUG_PRINT((ACPI_DB_INFO,
315*95b482a8SLen Brown 								  "Needed buffer size %X, %s\n",
316*95b482a8SLen Brown 								  (u32)
317*95b482a8SLen Brown 								  buffer_space_needed,
318*95b482a8SLen Brown 								  acpi_format_exception
319*95b482a8SLen Brown 								  (status)));
320*95b482a8SLen Brown 					} else {
321*95b482a8SLen Brown 						/* We have enough space for the object, build it */
322*95b482a8SLen Brown 
323*95b482a8SLen Brown 						status =
324*95b482a8SLen Brown 						    acpi_ut_copy_iobject_to_eobject
325*95b482a8SLen Brown 						    (info->return_object,
326*95b482a8SLen Brown 						     return_buffer);
327*95b482a8SLen Brown 					}
328*95b482a8SLen Brown 				}
329*95b482a8SLen Brown 			}
330*95b482a8SLen Brown 		}
331*95b482a8SLen Brown 	}
332*95b482a8SLen Brown 
333*95b482a8SLen Brown 	if (info->return_object) {
334*95b482a8SLen Brown 		/*
335*95b482a8SLen Brown 		 * Delete the internal return object. NOTE: Interpreter must be
336*95b482a8SLen Brown 		 * locked to avoid race condition.
337*95b482a8SLen Brown 		 */
338*95b482a8SLen Brown 		acpi_ex_enter_interpreter();
339*95b482a8SLen Brown 
340*95b482a8SLen Brown 		/* Remove one reference on the return object (should delete it) */
341*95b482a8SLen Brown 
342*95b482a8SLen Brown 		acpi_ut_remove_reference(info->return_object);
343*95b482a8SLen Brown 		acpi_ex_exit_interpreter();
344*95b482a8SLen Brown 	}
345*95b482a8SLen Brown 
346*95b482a8SLen Brown       cleanup:
347*95b482a8SLen Brown 
348*95b482a8SLen Brown 	/* Free the input parameter list (if we created one) */
349*95b482a8SLen Brown 
350*95b482a8SLen Brown 	if (info->parameters) {
351*95b482a8SLen Brown 
352*95b482a8SLen Brown 		/* Free the allocated parameter block */
353*95b482a8SLen Brown 
354*95b482a8SLen Brown 		acpi_ut_delete_internal_object_list(info->parameters);
355*95b482a8SLen Brown 	}
356*95b482a8SLen Brown 
357*95b482a8SLen Brown 	ACPI_FREE(info);
358*95b482a8SLen Brown 	return_ACPI_STATUS(status);
359*95b482a8SLen Brown }
360*95b482a8SLen Brown 
361*95b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_evaluate_object)
362*95b482a8SLen Brown 
363*95b482a8SLen Brown /*******************************************************************************
364*95b482a8SLen Brown  *
365*95b482a8SLen Brown  * FUNCTION:    acpi_ns_resolve_references
366*95b482a8SLen Brown  *
367*95b482a8SLen Brown  * PARAMETERS:  Info                    - Evaluation info block
368*95b482a8SLen Brown  *
369*95b482a8SLen Brown  * RETURN:      Info->return_object is replaced with the dereferenced object
370*95b482a8SLen Brown  *
371*95b482a8SLen Brown  * DESCRIPTION: Dereference certain reference objects. Called before an
372*95b482a8SLen Brown  *              internal return object is converted to an external union acpi_object.
373*95b482a8SLen Brown  *
374*95b482a8SLen Brown  * Performs an automatic dereference of Index and ref_of reference objects.
375*95b482a8SLen Brown  * These reference objects are not supported by the union acpi_object, so this is a
376*95b482a8SLen Brown  * last resort effort to return something useful. Also, provides compatibility
377*95b482a8SLen Brown  * with other ACPI implementations.
378*95b482a8SLen Brown  *
379*95b482a8SLen Brown  * NOTE: does not handle references within returned package objects or nested
380*95b482a8SLen Brown  * references, but this support could be added later if found to be necessary.
381*95b482a8SLen Brown  *
382*95b482a8SLen Brown  ******************************************************************************/
383*95b482a8SLen Brown static void acpi_ns_resolve_references(struct acpi_evaluate_info *info)
384*95b482a8SLen Brown {
385*95b482a8SLen Brown 	union acpi_operand_object *obj_desc = NULL;
386*95b482a8SLen Brown 	struct acpi_namespace_node *node;
387*95b482a8SLen Brown 
388*95b482a8SLen Brown 	/* We are interested in reference objects only */
389*95b482a8SLen Brown 
390*95b482a8SLen Brown 	if (ACPI_GET_OBJECT_TYPE(info->return_object) !=
391*95b482a8SLen Brown 	    ACPI_TYPE_LOCAL_REFERENCE) {
392*95b482a8SLen Brown 		return;
393*95b482a8SLen Brown 	}
394*95b482a8SLen Brown 
395*95b482a8SLen Brown 	/*
396*95b482a8SLen Brown 	 * Two types of references are supported - those created by Index and
397*95b482a8SLen Brown 	 * ref_of operators. A name reference (AML_NAMEPATH_OP) can be converted
398*95b482a8SLen Brown 	 * to an union acpi_object, so it is not dereferenced here. A ddb_handle
399*95b482a8SLen Brown 	 * (AML_LOAD_OP) cannot be dereferenced, nor can it be converted to
400*95b482a8SLen Brown 	 * an union acpi_object.
401*95b482a8SLen Brown 	 */
402*95b482a8SLen Brown 	switch (info->return_object->reference.class) {
403*95b482a8SLen Brown 	case ACPI_REFCLASS_INDEX:
404*95b482a8SLen Brown 
405*95b482a8SLen Brown 		obj_desc = *(info->return_object->reference.where);
406*95b482a8SLen Brown 		break;
407*95b482a8SLen Brown 
408*95b482a8SLen Brown 	case ACPI_REFCLASS_REFOF:
409*95b482a8SLen Brown 
410*95b482a8SLen Brown 		node = info->return_object->reference.object;
411*95b482a8SLen Brown 		if (node) {
412*95b482a8SLen Brown 			obj_desc = node->object;
413*95b482a8SLen Brown 		}
414*95b482a8SLen Brown 		break;
415*95b482a8SLen Brown 
416*95b482a8SLen Brown 	default:
417*95b482a8SLen Brown 		return;
418*95b482a8SLen Brown 	}
419*95b482a8SLen Brown 
420*95b482a8SLen Brown 	/* Replace the existing reference object */
421*95b482a8SLen Brown 
422*95b482a8SLen Brown 	if (obj_desc) {
423*95b482a8SLen Brown 		acpi_ut_add_reference(obj_desc);
424*95b482a8SLen Brown 		acpi_ut_remove_reference(info->return_object);
425*95b482a8SLen Brown 		info->return_object = obj_desc;
426*95b482a8SLen Brown 	}
427*95b482a8SLen Brown 
428*95b482a8SLen Brown 	return;
429*95b482a8SLen Brown }
430*95b482a8SLen Brown 
431*95b482a8SLen Brown /*******************************************************************************
432*95b482a8SLen Brown  *
433*95b482a8SLen Brown  * FUNCTION:    acpi_walk_namespace
434*95b482a8SLen Brown  *
435*95b482a8SLen Brown  * PARAMETERS:  Type                - acpi_object_type to search for
436*95b482a8SLen Brown  *              start_object        - Handle in namespace where search begins
437*95b482a8SLen Brown  *              max_depth           - Depth to which search is to reach
438*95b482a8SLen Brown  *              user_function       - Called when an object of "Type" is found
439*95b482a8SLen Brown  *              Context             - Passed to user function
440*95b482a8SLen Brown  *              return_value        - Location where return value of
441*95b482a8SLen Brown  *                                    user_function is put if terminated early
442*95b482a8SLen Brown  *
443*95b482a8SLen Brown  * RETURNS      Return value from the user_function if terminated early.
444*95b482a8SLen Brown  *              Otherwise, returns NULL.
445*95b482a8SLen Brown  *
446*95b482a8SLen Brown  * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
447*95b482a8SLen Brown  *              starting (and ending) at the object specified by start_handle.
448*95b482a8SLen Brown  *              The user_function is called whenever an object that matches
449*95b482a8SLen Brown  *              the type parameter is found.  If the user function returns
450*95b482a8SLen Brown  *              a non-zero value, the search is terminated immediately and this
451*95b482a8SLen Brown  *              value is returned to the caller.
452*95b482a8SLen Brown  *
453*95b482a8SLen Brown  *              The point of this procedure is to provide a generic namespace
454*95b482a8SLen Brown  *              walk routine that can be called from multiple places to
455*95b482a8SLen Brown  *              provide multiple services;  the User Function can be tailored
456*95b482a8SLen Brown  *              to each task, whether it is a print function, a compare
457*95b482a8SLen Brown  *              function, etc.
458*95b482a8SLen Brown  *
459*95b482a8SLen Brown  ******************************************************************************/
460*95b482a8SLen Brown 
461*95b482a8SLen Brown acpi_status
462*95b482a8SLen Brown acpi_walk_namespace(acpi_object_type type,
463*95b482a8SLen Brown 		    acpi_handle start_object,
464*95b482a8SLen Brown 		    u32 max_depth,
465*95b482a8SLen Brown 		    acpi_walk_callback user_function,
466*95b482a8SLen Brown 		    void *context, void **return_value)
467*95b482a8SLen Brown {
468*95b482a8SLen Brown 	acpi_status status;
469*95b482a8SLen Brown 
470*95b482a8SLen Brown 	ACPI_FUNCTION_TRACE(acpi_walk_namespace);
471*95b482a8SLen Brown 
472*95b482a8SLen Brown 	/* Parameter validation */
473*95b482a8SLen Brown 
474*95b482a8SLen Brown 	if ((type > ACPI_TYPE_LOCAL_MAX) || (!max_depth) || (!user_function)) {
475*95b482a8SLen Brown 		return_ACPI_STATUS(AE_BAD_PARAMETER);
476*95b482a8SLen Brown 	}
477*95b482a8SLen Brown 
478*95b482a8SLen Brown 	/*
479*95b482a8SLen Brown 	 * Lock the namespace around the walk.
480*95b482a8SLen Brown 	 * The namespace will be unlocked/locked around each call
481*95b482a8SLen Brown 	 * to the user function - since this function
482*95b482a8SLen Brown 	 * must be allowed to make Acpi calls itself.
483*95b482a8SLen Brown 	 */
484*95b482a8SLen Brown 	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
485*95b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
486*95b482a8SLen Brown 		return_ACPI_STATUS(status);
487*95b482a8SLen Brown 	}
488*95b482a8SLen Brown 
489*95b482a8SLen Brown 	status = acpi_ns_walk_namespace(type, start_object, max_depth,
490*95b482a8SLen Brown 					ACPI_NS_WALK_UNLOCK,
491*95b482a8SLen Brown 					user_function, context, return_value);
492*95b482a8SLen Brown 
493*95b482a8SLen Brown 	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
494*95b482a8SLen Brown 	return_ACPI_STATUS(status);
495*95b482a8SLen Brown }
496*95b482a8SLen Brown 
497*95b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_walk_namespace)
498*95b482a8SLen Brown 
499*95b482a8SLen Brown /*******************************************************************************
500*95b482a8SLen Brown  *
501*95b482a8SLen Brown  * FUNCTION:    acpi_ns_get_device_callback
502*95b482a8SLen Brown  *
503*95b482a8SLen Brown  * PARAMETERS:  Callback from acpi_get_device
504*95b482a8SLen Brown  *
505*95b482a8SLen Brown  * RETURN:      Status
506*95b482a8SLen Brown  *
507*95b482a8SLen Brown  * DESCRIPTION: Takes callbacks from walk_namespace and filters out all non-
508*95b482a8SLen Brown  *              present devices, or if they specified a HID, it filters based
509*95b482a8SLen Brown  *              on that.
510*95b482a8SLen Brown  *
511*95b482a8SLen Brown  ******************************************************************************/
512*95b482a8SLen Brown static acpi_status
513*95b482a8SLen Brown acpi_ns_get_device_callback(acpi_handle obj_handle,
514*95b482a8SLen Brown 			    u32 nesting_level,
515*95b482a8SLen Brown 			    void *context, void **return_value)
516*95b482a8SLen Brown {
517*95b482a8SLen Brown 	struct acpi_get_devices_info *info = context;
518*95b482a8SLen Brown 	acpi_status status;
519*95b482a8SLen Brown 	struct acpi_namespace_node *node;
520*95b482a8SLen Brown 	u32 flags;
521*95b482a8SLen Brown 	struct acpica_device_id hid;
522*95b482a8SLen Brown 	struct acpi_compatible_id_list *cid;
523*95b482a8SLen Brown 	u32 i;
524*95b482a8SLen Brown 	int found;
525*95b482a8SLen Brown 
526*95b482a8SLen Brown 	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
527*95b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
528*95b482a8SLen Brown 		return (status);
529*95b482a8SLen Brown 	}
530*95b482a8SLen Brown 
531*95b482a8SLen Brown 	node = acpi_ns_map_handle_to_node(obj_handle);
532*95b482a8SLen Brown 	status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
533*95b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
534*95b482a8SLen Brown 		return (status);
535*95b482a8SLen Brown 	}
536*95b482a8SLen Brown 
537*95b482a8SLen Brown 	if (!node) {
538*95b482a8SLen Brown 		return (AE_BAD_PARAMETER);
539*95b482a8SLen Brown 	}
540*95b482a8SLen Brown 
541*95b482a8SLen Brown 	/* Run _STA to determine if device is present */
542*95b482a8SLen Brown 
543*95b482a8SLen Brown 	status = acpi_ut_execute_STA(node, &flags);
544*95b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
545*95b482a8SLen Brown 		return (AE_CTRL_DEPTH);
546*95b482a8SLen Brown 	}
547*95b482a8SLen Brown 
548*95b482a8SLen Brown 	if (!(flags & ACPI_STA_DEVICE_PRESENT) &&
549*95b482a8SLen Brown 	    !(flags & ACPI_STA_DEVICE_FUNCTIONING)) {
550*95b482a8SLen Brown 		/*
551*95b482a8SLen Brown 		 * Don't examine the children of the device only when the
552*95b482a8SLen Brown 		 * device is neither present nor functional. See ACPI spec,
553*95b482a8SLen Brown 		 * description of _STA for more information.
554*95b482a8SLen Brown 		 */
555*95b482a8SLen Brown 		return (AE_CTRL_DEPTH);
556*95b482a8SLen Brown 	}
557*95b482a8SLen Brown 
558*95b482a8SLen Brown 	/* Filter based on device HID & CID */
559*95b482a8SLen Brown 
560*95b482a8SLen Brown 	if (info->hid != NULL) {
561*95b482a8SLen Brown 		status = acpi_ut_execute_HID(node, &hid);
562*95b482a8SLen Brown 		if (status == AE_NOT_FOUND) {
563*95b482a8SLen Brown 			return (AE_OK);
564*95b482a8SLen Brown 		} else if (ACPI_FAILURE(status)) {
565*95b482a8SLen Brown 			return (AE_CTRL_DEPTH);
566*95b482a8SLen Brown 		}
567*95b482a8SLen Brown 
568*95b482a8SLen Brown 		if (ACPI_STRNCMP(hid.value, info->hid, sizeof(hid.value)) != 0) {
569*95b482a8SLen Brown 
570*95b482a8SLen Brown 			/* Get the list of Compatible IDs */
571*95b482a8SLen Brown 
572*95b482a8SLen Brown 			status = acpi_ut_execute_CID(node, &cid);
573*95b482a8SLen Brown 			if (status == AE_NOT_FOUND) {
574*95b482a8SLen Brown 				return (AE_OK);
575*95b482a8SLen Brown 			} else if (ACPI_FAILURE(status)) {
576*95b482a8SLen Brown 				return (AE_CTRL_DEPTH);
577*95b482a8SLen Brown 			}
578*95b482a8SLen Brown 
579*95b482a8SLen Brown 			/* Walk the CID list */
580*95b482a8SLen Brown 
581*95b482a8SLen Brown 			found = 0;
582*95b482a8SLen Brown 			for (i = 0; i < cid->count; i++) {
583*95b482a8SLen Brown 				if (ACPI_STRNCMP(cid->id[i].value, info->hid,
584*95b482a8SLen Brown 						 sizeof(struct
585*95b482a8SLen Brown 							acpi_compatible_id)) ==
586*95b482a8SLen Brown 				    0) {
587*95b482a8SLen Brown 					found = 1;
588*95b482a8SLen Brown 					break;
589*95b482a8SLen Brown 				}
590*95b482a8SLen Brown 			}
591*95b482a8SLen Brown 			ACPI_FREE(cid);
592*95b482a8SLen Brown 			if (!found)
593*95b482a8SLen Brown 				return (AE_OK);
594*95b482a8SLen Brown 		}
595*95b482a8SLen Brown 	}
596*95b482a8SLen Brown 
597*95b482a8SLen Brown 	status = info->user_function(obj_handle, nesting_level, info->context,
598*95b482a8SLen Brown 				     return_value);
599*95b482a8SLen Brown 	return (status);
600*95b482a8SLen Brown }
601*95b482a8SLen Brown 
602*95b482a8SLen Brown /*******************************************************************************
603*95b482a8SLen Brown  *
604*95b482a8SLen Brown  * FUNCTION:    acpi_get_devices
605*95b482a8SLen Brown  *
606*95b482a8SLen Brown  * PARAMETERS:  HID                 - HID to search for. Can be NULL.
607*95b482a8SLen Brown  *              user_function       - Called when a matching object is found
608*95b482a8SLen Brown  *              Context             - Passed to user function
609*95b482a8SLen Brown  *              return_value        - Location where return value of
610*95b482a8SLen Brown  *                                    user_function is put if terminated early
611*95b482a8SLen Brown  *
612*95b482a8SLen Brown  * RETURNS      Return value from the user_function if terminated early.
613*95b482a8SLen Brown  *              Otherwise, returns NULL.
614*95b482a8SLen Brown  *
615*95b482a8SLen Brown  * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
616*95b482a8SLen Brown  *              starting (and ending) at the object specified by start_handle.
617*95b482a8SLen Brown  *              The user_function is called whenever an object of type
618*95b482a8SLen Brown  *              Device is found.  If the user function returns
619*95b482a8SLen Brown  *              a non-zero value, the search is terminated immediately and this
620*95b482a8SLen Brown  *              value is returned to the caller.
621*95b482a8SLen Brown  *
622*95b482a8SLen Brown  *              This is a wrapper for walk_namespace, but the callback performs
623*95b482a8SLen Brown  *              additional filtering. Please see acpi_ns_get_device_callback.
624*95b482a8SLen Brown  *
625*95b482a8SLen Brown  ******************************************************************************/
626*95b482a8SLen Brown 
627*95b482a8SLen Brown acpi_status
628*95b482a8SLen Brown acpi_get_devices(const char *HID,
629*95b482a8SLen Brown 		 acpi_walk_callback user_function,
630*95b482a8SLen Brown 		 void *context, void **return_value)
631*95b482a8SLen Brown {
632*95b482a8SLen Brown 	acpi_status status;
633*95b482a8SLen Brown 	struct acpi_get_devices_info info;
634*95b482a8SLen Brown 
635*95b482a8SLen Brown 	ACPI_FUNCTION_TRACE(acpi_get_devices);
636*95b482a8SLen Brown 
637*95b482a8SLen Brown 	/* Parameter validation */
638*95b482a8SLen Brown 
639*95b482a8SLen Brown 	if (!user_function) {
640*95b482a8SLen Brown 		return_ACPI_STATUS(AE_BAD_PARAMETER);
641*95b482a8SLen Brown 	}
642*95b482a8SLen Brown 
643*95b482a8SLen Brown 	/*
644*95b482a8SLen Brown 	 * We're going to call their callback from OUR callback, so we need
645*95b482a8SLen Brown 	 * to know what it is, and their context parameter.
646*95b482a8SLen Brown 	 */
647*95b482a8SLen Brown 	info.hid = HID;
648*95b482a8SLen Brown 	info.context = context;
649*95b482a8SLen Brown 	info.user_function = user_function;
650*95b482a8SLen Brown 
651*95b482a8SLen Brown 	/*
652*95b482a8SLen Brown 	 * Lock the namespace around the walk.
653*95b482a8SLen Brown 	 * The namespace will be unlocked/locked around each call
654*95b482a8SLen Brown 	 * to the user function - since this function
655*95b482a8SLen Brown 	 * must be allowed to make Acpi calls itself.
656*95b482a8SLen Brown 	 */
657*95b482a8SLen Brown 	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
658*95b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
659*95b482a8SLen Brown 		return_ACPI_STATUS(status);
660*95b482a8SLen Brown 	}
661*95b482a8SLen Brown 
662*95b482a8SLen Brown 	status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
663*95b482a8SLen Brown 					ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
664*95b482a8SLen Brown 					acpi_ns_get_device_callback, &info,
665*95b482a8SLen Brown 					return_value);
666*95b482a8SLen Brown 
667*95b482a8SLen Brown 	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
668*95b482a8SLen Brown 	return_ACPI_STATUS(status);
669*95b482a8SLen Brown }
670*95b482a8SLen Brown 
671*95b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_get_devices)
672*95b482a8SLen Brown 
673*95b482a8SLen Brown /*******************************************************************************
674*95b482a8SLen Brown  *
675*95b482a8SLen Brown  * FUNCTION:    acpi_attach_data
676*95b482a8SLen Brown  *
677*95b482a8SLen Brown  * PARAMETERS:  obj_handle          - Namespace node
678*95b482a8SLen Brown  *              Handler             - Handler for this attachment
679*95b482a8SLen Brown  *              Data                - Pointer to data to be attached
680*95b482a8SLen Brown  *
681*95b482a8SLen Brown  * RETURN:      Status
682*95b482a8SLen Brown  *
683*95b482a8SLen Brown  * DESCRIPTION: Attach arbitrary data and handler to a namespace node.
684*95b482a8SLen Brown  *
685*95b482a8SLen Brown  ******************************************************************************/
686*95b482a8SLen Brown acpi_status
687*95b482a8SLen Brown acpi_attach_data(acpi_handle obj_handle,
688*95b482a8SLen Brown 		 acpi_object_handler handler, void *data)
689*95b482a8SLen Brown {
690*95b482a8SLen Brown 	struct acpi_namespace_node *node;
691*95b482a8SLen Brown 	acpi_status status;
692*95b482a8SLen Brown 
693*95b482a8SLen Brown 	/* Parameter validation */
694*95b482a8SLen Brown 
695*95b482a8SLen Brown 	if (!obj_handle || !handler || !data) {
696*95b482a8SLen Brown 		return (AE_BAD_PARAMETER);
697*95b482a8SLen Brown 	}
698*95b482a8SLen Brown 
699*95b482a8SLen Brown 	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
700*95b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
701*95b482a8SLen Brown 		return (status);
702*95b482a8SLen Brown 	}
703*95b482a8SLen Brown 
704*95b482a8SLen Brown 	/* Convert and validate the handle */
705*95b482a8SLen Brown 
706*95b482a8SLen Brown 	node = acpi_ns_map_handle_to_node(obj_handle);
707*95b482a8SLen Brown 	if (!node) {
708*95b482a8SLen Brown 		status = AE_BAD_PARAMETER;
709*95b482a8SLen Brown 		goto unlock_and_exit;
710*95b482a8SLen Brown 	}
711*95b482a8SLen Brown 
712*95b482a8SLen Brown 	status = acpi_ns_attach_data(node, handler, data);
713*95b482a8SLen Brown 
714*95b482a8SLen Brown       unlock_and_exit:
715*95b482a8SLen Brown 	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
716*95b482a8SLen Brown 	return (status);
717*95b482a8SLen Brown }
718*95b482a8SLen Brown 
719*95b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_attach_data)
720*95b482a8SLen Brown 
721*95b482a8SLen Brown /*******************************************************************************
722*95b482a8SLen Brown  *
723*95b482a8SLen Brown  * FUNCTION:    acpi_detach_data
724*95b482a8SLen Brown  *
725*95b482a8SLen Brown  * PARAMETERS:  obj_handle          - Namespace node handle
726*95b482a8SLen Brown  *              Handler             - Handler used in call to acpi_attach_data
727*95b482a8SLen Brown  *
728*95b482a8SLen Brown  * RETURN:      Status
729*95b482a8SLen Brown  *
730*95b482a8SLen Brown  * DESCRIPTION: Remove data that was previously attached to a node.
731*95b482a8SLen Brown  *
732*95b482a8SLen Brown  ******************************************************************************/
733*95b482a8SLen Brown acpi_status
734*95b482a8SLen Brown acpi_detach_data(acpi_handle obj_handle, acpi_object_handler handler)
735*95b482a8SLen Brown {
736*95b482a8SLen Brown 	struct acpi_namespace_node *node;
737*95b482a8SLen Brown 	acpi_status status;
738*95b482a8SLen Brown 
739*95b482a8SLen Brown 	/* Parameter validation */
740*95b482a8SLen Brown 
741*95b482a8SLen Brown 	if (!obj_handle || !handler) {
742*95b482a8SLen Brown 		return (AE_BAD_PARAMETER);
743*95b482a8SLen Brown 	}
744*95b482a8SLen Brown 
745*95b482a8SLen Brown 	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
746*95b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
747*95b482a8SLen Brown 		return (status);
748*95b482a8SLen Brown 	}
749*95b482a8SLen Brown 
750*95b482a8SLen Brown 	/* Convert and validate the handle */
751*95b482a8SLen Brown 
752*95b482a8SLen Brown 	node = acpi_ns_map_handle_to_node(obj_handle);
753*95b482a8SLen Brown 	if (!node) {
754*95b482a8SLen Brown 		status = AE_BAD_PARAMETER;
755*95b482a8SLen Brown 		goto unlock_and_exit;
756*95b482a8SLen Brown 	}
757*95b482a8SLen Brown 
758*95b482a8SLen Brown 	status = acpi_ns_detach_data(node, handler);
759*95b482a8SLen Brown 
760*95b482a8SLen Brown       unlock_and_exit:
761*95b482a8SLen Brown 	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
762*95b482a8SLen Brown 	return (status);
763*95b482a8SLen Brown }
764*95b482a8SLen Brown 
765*95b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_detach_data)
766*95b482a8SLen Brown 
767*95b482a8SLen Brown /*******************************************************************************
768*95b482a8SLen Brown  *
769*95b482a8SLen Brown  * FUNCTION:    acpi_get_data
770*95b482a8SLen Brown  *
771*95b482a8SLen Brown  * PARAMETERS:  obj_handle          - Namespace node
772*95b482a8SLen Brown  *              Handler             - Handler used in call to attach_data
773*95b482a8SLen Brown  *              Data                - Where the data is returned
774*95b482a8SLen Brown  *
775*95b482a8SLen Brown  * RETURN:      Status
776*95b482a8SLen Brown  *
777*95b482a8SLen Brown  * DESCRIPTION: Retrieve data that was previously attached to a namespace node.
778*95b482a8SLen Brown  *
779*95b482a8SLen Brown  ******************************************************************************/
780*95b482a8SLen Brown acpi_status
781*95b482a8SLen Brown acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data)
782*95b482a8SLen Brown {
783*95b482a8SLen Brown 	struct acpi_namespace_node *node;
784*95b482a8SLen Brown 	acpi_status status;
785*95b482a8SLen Brown 
786*95b482a8SLen Brown 	/* Parameter validation */
787*95b482a8SLen Brown 
788*95b482a8SLen Brown 	if (!obj_handle || !handler || !data) {
789*95b482a8SLen Brown 		return (AE_BAD_PARAMETER);
790*95b482a8SLen Brown 	}
791*95b482a8SLen Brown 
792*95b482a8SLen Brown 	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
793*95b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
794*95b482a8SLen Brown 		return (status);
795*95b482a8SLen Brown 	}
796*95b482a8SLen Brown 
797*95b482a8SLen Brown 	/* Convert and validate the handle */
798*95b482a8SLen Brown 
799*95b482a8SLen Brown 	node = acpi_ns_map_handle_to_node(obj_handle);
800*95b482a8SLen Brown 	if (!node) {
801*95b482a8SLen Brown 		status = AE_BAD_PARAMETER;
802*95b482a8SLen Brown 		goto unlock_and_exit;
803*95b482a8SLen Brown 	}
804*95b482a8SLen Brown 
805*95b482a8SLen Brown 	status = acpi_ns_get_attached_data(node, handler, data);
806*95b482a8SLen Brown 
807*95b482a8SLen Brown       unlock_and_exit:
808*95b482a8SLen Brown 	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
809*95b482a8SLen Brown 	return (status);
810*95b482a8SLen Brown }
811*95b482a8SLen Brown 
812*95b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_get_data)
813