Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
nsobject.c
Go to the documentation of this file.
1 /*******************************************************************************
2  *
3  * Module Name: nsobject - Utilities for objects attached to namespace
4  * table entries
5  *
6  ******************************************************************************/
7 
8 /*
9  * Copyright (C) 2000 - 2012, Intel Corp.
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  * notice, this list of conditions, and the following disclaimer,
17  * without modification.
18  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19  * substantially similar to the "NO WARRANTY" disclaimer below
20  * ("Disclaimer") and any redistribution must be conditioned upon
21  * including a substantially similar Disclaimer requirement for further
22  * binary redistribution.
23  * 3. Neither the names of the above-listed copyright holders nor the names
24  * of any contributors may be used to endorse or promote products derived
25  * from this software without specific prior written permission.
26  *
27  * Alternatively, this software may be distributed under the terms of the
28  * GNU General Public License ("GPL") version 2 as published by the Free
29  * Software Foundation.
30  *
31  * NO WARRANTY
32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42  * POSSIBILITY OF SUCH DAMAGES.
43  */
44 
45 #include <acpi/acpi.h>
46 #include "accommon.h"
47 #include "acnamesp.h"
48 
49 #define _COMPONENT ACPI_NAMESPACE
50 ACPI_MODULE_NAME("nsobject")
51 
52 /*******************************************************************************
53  *
54  * FUNCTION: acpi_ns_attach_object
55  *
56  * PARAMETERS: node - Parent Node
57  * object - Object to be attached
58  * type - Type of object, or ACPI_TYPE_ANY if not
59  * known
60  *
61  * RETURN: Status
62  *
63  * DESCRIPTION: Record the given object as the value associated with the
64  * name whose acpi_handle is passed. If Object is NULL
65  * and Type is ACPI_TYPE_ANY, set the name as having no value.
66  * Note: Future may require that the Node->Flags field be passed
67  * as a parameter.
68  *
69  * MUTEX: Assumes namespace is locked
70  *
71  ******************************************************************************/
75 {
76  union acpi_operand_object *obj_desc;
77  union acpi_operand_object *last_obj_desc;
79 
80  ACPI_FUNCTION_TRACE(ns_attach_object);
81 
82  /*
83  * Parameter validation
84  */
85  if (!node) {
86 
87  /* Invalid handle */
88 
89  ACPI_ERROR((AE_INFO, "Null NamedObj handle"));
91  }
92 
93  if (!object && (ACPI_TYPE_ANY != type)) {
94 
95  /* Null object */
96 
98  "Null object, but type not ACPI_TYPE_ANY"));
100  }
101 
103 
104  /* Not a name handle */
105 
106  ACPI_ERROR((AE_INFO, "Invalid handle %p [%s]",
107  node, acpi_ut_get_descriptor_name(node)));
109  }
110 
111  /* Check if this object is already attached */
112 
113  if (node->object == object) {
115  "Obj %p already installed in NameObj %p\n",
116  object, node));
117 
119  }
120 
121  /* If null object, we will just install it */
122 
123  if (!object) {
124  obj_desc = NULL;
125  object_type = ACPI_TYPE_ANY;
126  }
127 
128  /*
129  * If the source object is a namespace Node with an attached object,
130  * we will use that (attached) object
131  */
132  else if ((ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED) &&
133  ((struct acpi_namespace_node *)object)->object) {
134  /*
135  * Value passed is a name handle and that name has a
136  * non-null value. Use that name's value and type.
137  */
138  obj_desc = ((struct acpi_namespace_node *)object)->object;
139  object_type = ((struct acpi_namespace_node *)object)->type;
140  }
141 
142  /*
143  * Otherwise, we will use the parameter object, but we must type
144  * it first
145  */
146  else {
147  obj_desc = (union acpi_operand_object *)object;
148 
149  /* Use the given type */
150 
151  object_type = type;
152  }
153 
154  ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Installing %p into Node %p [%4.4s]\n",
155  obj_desc, node, acpi_ut_get_node_name(node)));
156 
157  /* Detach an existing attached object if present */
158 
159  if (node->object) {
160  acpi_ns_detach_object(node);
161  }
162 
163  if (obj_desc) {
164  /*
165  * Must increment the new value's reference count
166  * (if it is an internal object)
167  */
168  acpi_ut_add_reference(obj_desc);
169 
170  /*
171  * Handle objects with multiple descriptors - walk
172  * to the end of the descriptor list
173  */
174  last_obj_desc = obj_desc;
175  while (last_obj_desc->common.next_object) {
176  last_obj_desc = last_obj_desc->common.next_object;
177  }
178 
179  /* Install the object at the front of the object list */
180 
181  last_obj_desc->common.next_object = node->object;
182  }
183 
184  node->type = (u8) object_type;
185  node->object = obj_desc;
186 
188 }
189 
190 /*******************************************************************************
191  *
192  * FUNCTION: acpi_ns_detach_object
193  *
194  * PARAMETERS: node - A Namespace node whose object will be detached
195  *
196  * RETURN: None.
197  *
198  * DESCRIPTION: Detach/delete an object associated with a namespace node.
199  * if the object is an allocated object, it is freed.
200  * Otherwise, the field is simply cleared.
201  *
202  ******************************************************************************/
203 
205 {
206  union acpi_operand_object *obj_desc;
207 
208  ACPI_FUNCTION_TRACE(ns_detach_object);
209 
210  obj_desc = node->object;
211 
212  if (!obj_desc || (obj_desc->common.type == ACPI_TYPE_LOCAL_DATA)) {
213  return_VOID;
214  }
215 
216  if (node->flags & ANOBJ_ALLOCATED_BUFFER) {
217 
218  /* Free the dynamic aml buffer */
219 
220  if (obj_desc->common.type == ACPI_TYPE_METHOD) {
221  ACPI_FREE(obj_desc->method.aml_start);
222  }
223  }
224 
225  /* Clear the entry in all cases */
226 
227  node->object = NULL;
229  node->object = obj_desc->common.next_object;
230  if (node->object &&
231  ((node->object)->common.type != ACPI_TYPE_LOCAL_DATA)) {
232  node->object = node->object->common.next_object;
233  }
234  }
235 
236  /* Reset the node type to untyped */
237 
238  node->type = ACPI_TYPE_ANY;
239 
240  ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Node %p [%4.4s] Object %p\n",
241  node, acpi_ut_get_node_name(node), obj_desc));
242 
243  /* Remove one reference on the object (and all subobjects) */
244 
245  acpi_ut_remove_reference(obj_desc);
246  return_VOID;
247 }
248 
249 /*******************************************************************************
250  *
251  * FUNCTION: acpi_ns_get_attached_object
252  *
253  * PARAMETERS: node - Namespace node
254  *
255  * RETURN: Current value of the object field from the Node whose
256  * handle is passed
257  *
258  * DESCRIPTION: Obtain the object attached to a namespace node.
259  *
260  ******************************************************************************/
261 
264  *node)
265 {
266  ACPI_FUNCTION_TRACE_PTR(ns_get_attached_object, node);
267 
268  if (!node) {
269  ACPI_WARNING((AE_INFO, "Null Node ptr"));
270  return_PTR(NULL);
271  }
272 
273  if (!node->object ||
275  && (ACPI_GET_DESCRIPTOR_TYPE(node->object) !=
277  || ((node->object)->common.type == ACPI_TYPE_LOCAL_DATA)) {
278  return_PTR(NULL);
279  }
280 
281  return_PTR(node->object);
282 }
283 
284 /*******************************************************************************
285  *
286  * FUNCTION: acpi_ns_get_secondary_object
287  *
288  * PARAMETERS: node - Namespace node
289  *
290  * RETURN: Current value of the object field from the Node whose
291  * handle is passed.
292  *
293  * DESCRIPTION: Obtain a secondary object associated with a namespace node.
294  *
295  ******************************************************************************/
296 
299  *obj_desc)
300 {
301  ACPI_FUNCTION_TRACE_PTR(ns_get_secondary_object, obj_desc);
302 
303  if ((!obj_desc) ||
304  (obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) ||
305  (!obj_desc->common.next_object) ||
306  ((obj_desc->common.next_object)->common.type ==
308  return_PTR(NULL);
309  }
310 
311  return_PTR(obj_desc->common.next_object);
312 }
313 
314 /*******************************************************************************
315  *
316  * FUNCTION: acpi_ns_attach_data
317  *
318  * PARAMETERS: node - Namespace node
319  * handler - Handler to be associated with the data
320  * data - Data to be attached
321  *
322  * RETURN: Status
323  *
324  * DESCRIPTION: Low-level attach data. Create and attach a Data object.
325  *
326  ******************************************************************************/
327 
330  acpi_object_handler handler, void *data)
331 {
332  union acpi_operand_object *prev_obj_desc;
333  union acpi_operand_object *obj_desc;
334  union acpi_operand_object *data_desc;
335 
336  /* We only allow one attachment per handler */
337 
338  prev_obj_desc = NULL;
339  obj_desc = node->object;
340  while (obj_desc) {
341  if ((obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) &&
342  (obj_desc->data.handler == handler)) {
343  return (AE_ALREADY_EXISTS);
344  }
345 
346  prev_obj_desc = obj_desc;
347  obj_desc = obj_desc->common.next_object;
348  }
349 
350  /* Create an internal object for the data */
351 
353  if (!data_desc) {
354  return (AE_NO_MEMORY);
355  }
356 
357  data_desc->data.handler = handler;
358  data_desc->data.pointer = data;
359 
360  /* Install the data object */
361 
362  if (prev_obj_desc) {
363  prev_obj_desc->common.next_object = data_desc;
364  } else {
365  node->object = data_desc;
366  }
367 
368  return (AE_OK);
369 }
370 
371 /*******************************************************************************
372  *
373  * FUNCTION: acpi_ns_detach_data
374  *
375  * PARAMETERS: node - Namespace node
376  * handler - Handler associated with the data
377  *
378  * RETURN: Status
379  *
380  * DESCRIPTION: Low-level detach data. Delete the data node, but the caller
381  * is responsible for the actual data.
382  *
383  ******************************************************************************/
384 
387  acpi_object_handler handler)
388 {
389  union acpi_operand_object *obj_desc;
390  union acpi_operand_object *prev_obj_desc;
391 
392  prev_obj_desc = NULL;
393  obj_desc = node->object;
394  while (obj_desc) {
395  if ((obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) &&
396  (obj_desc->data.handler == handler)) {
397  if (prev_obj_desc) {
398  prev_obj_desc->common.next_object =
399  obj_desc->common.next_object;
400  } else {
401  node->object = obj_desc->common.next_object;
402  }
403 
404  acpi_ut_remove_reference(obj_desc);
405  return (AE_OK);
406  }
407 
408  prev_obj_desc = obj_desc;
409  obj_desc = obj_desc->common.next_object;
410  }
411 
412  return (AE_NOT_FOUND);
413 }
414 
415 /*******************************************************************************
416  *
417  * FUNCTION: acpi_ns_get_attached_data
418  *
419  * PARAMETERS: node - Namespace node
420  * handler - Handler associated with the data
421  * data - Where the data is returned
422  *
423  * RETURN: Status
424  *
425  * DESCRIPTION: Low level interface to obtain data previously associated with
426  * a namespace node.
427  *
428  ******************************************************************************/
429 
432  acpi_object_handler handler, void **data)
433 {
434  union acpi_operand_object *obj_desc;
435 
436  obj_desc = node->object;
437  while (obj_desc) {
438  if ((obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) &&
439  (obj_desc->data.handler == handler)) {
440  *data = obj_desc->data.pointer;
441  return (AE_OK);
442  }
443 
444  obj_desc = obj_desc->common.next_object;
445  }
446 
447  return (AE_NOT_FOUND);
448 }