File: /usr/src/linux/drivers/acpi/dispatcher/dsmethod.c

1     /******************************************************************************
2      *
3      * Module Name: dsmethod - Parser/Interpreter interface - control method parsing
4      *              $Revision: 65 $
5      *
6      *****************************************************************************/
7     
8     /*
9      *  Copyright (C) 2000, 2001 R. Byron Moore
10      *
11      *  This program is free software; you can redistribute it and/or modify
12      *  it under the terms of the GNU General Public License as published by
13      *  the Free Software Foundation; either version 2 of the License, or
14      *  (at your option) any later version.
15      *
16      *  This program is distributed in the hope that it will be useful,
17      *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18      *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19      *  GNU General Public License for more details.
20      *
21      *  You should have received a copy of the GNU General Public License
22      *  along with this program; if not, write to the Free Software
23      *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24      */
25     
26     
27     #include "acpi.h"
28     #include "acparser.h"
29     #include "amlcode.h"
30     #include "acdispat.h"
31     #include "acinterp.h"
32     #include "acnamesp.h"
33     #include "actables.h"
34     #include "acdebug.h"
35     
36     
37     #define _COMPONENT          ACPI_DISPATCHER
38     	 MODULE_NAME         ("dsmethod")
39     
40     
41     /*******************************************************************************
42      *
43      * FUNCTION:    Acpi_ds_parse_method
44      *
45      * PARAMETERS:  Obj_handle      - Node of the method
46      *              Level           - Current nesting level
47      *              Context         - Points to a method counter
48      *              Return_value    - Not used
49      *
50      * RETURN:      Status
51      *
52      * DESCRIPTION: Call the parser and parse the AML that is
53      *              associated with the method.
54      *
55      * MUTEX:       Assumes parser is locked
56      *
57      ******************************************************************************/
58     
59     acpi_status
60     acpi_ds_parse_method (
61     	acpi_handle             obj_handle)
62     {
63     	acpi_status             status;
64     	acpi_operand_object     *obj_desc;
65     	acpi_parse_object       *op;
66     	acpi_namespace_node     *node;
67     	acpi_owner_id           owner_id;
68     
69     
70     	FUNCTION_TRACE_PTR ("Ds_parse_method", obj_handle);
71     
72     
73     	/* Parameter Validation */
74     
75     	if (!obj_handle) {
76     		return_ACPI_STATUS (AE_NULL_ENTRY);
77     	}
78     
79     	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "**** Parsing [%4.4s] **** Named_obj=%p\n",
80     		&((acpi_namespace_node *)obj_handle)->name, obj_handle));
81     
82     
83     	/* Extract the method object from the method Node */
84     
85     	node = (acpi_namespace_node *) obj_handle;
86     	obj_desc = node->object;
87     	if (!obj_desc) {
88     		return_ACPI_STATUS (AE_NULL_OBJECT);
89     	}
90     
91     	 /* Create a mutex for the method if there is a concurrency limit */
92     
93     	if ((obj_desc->method.concurrency != INFINITE_CONCURRENCY) &&
94     		(!obj_desc->method.semaphore)) {
95     		status = acpi_os_create_semaphore (obj_desc->method.concurrency,
96     				   obj_desc->method.concurrency,
97     				   &obj_desc->method.semaphore);
98     		if (ACPI_FAILURE (status)) {
99     			return_ACPI_STATUS (status);
100     		}
101     	}
102     
103     	/*
104     	 * Allocate a new parser op to be the root of the parsed
105     	 * method tree
106     	 */
107     	op = acpi_ps_alloc_op (AML_METHOD_OP);
108     	if (!op) {
109     		return_ACPI_STATUS (AE_NO_MEMORY);
110     	}
111     
112     	/* Init new op with the method name and pointer back to the Node */
113     
114     	acpi_ps_set_name (op, node->name);
115     	op->node = node;
116     
117     
118     	/*
119     	 * Parse the method, first pass
120     	 *
121     	 * The first pass load is where newly declared named objects are
122     	 * added into the namespace.  Actual evaluation of
123     	 * the named objects (what would be called a "second
124     	 * pass") happens during the actual execution of the
125     	 * method so that operands to the named objects can
126     	 * take on dynamic run-time values.
127     	 */
128     	status = acpi_ps_parse_aml (op, obj_desc->method.pcode,
129     			   obj_desc->method.pcode_length,
130     			   ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE,
131     			   node, NULL, NULL,
132     			   acpi_ds_load1_begin_op, acpi_ds_load1_end_op);
133     
134     	if (ACPI_FAILURE (status)) {
135     		return_ACPI_STATUS (status);
136     	}
137     
138     	/* Get a new Owner_id for objects created by this method */
139     
140     	owner_id = acpi_ut_allocate_owner_id (OWNER_TYPE_METHOD);
141     	obj_desc->method.owning_id = owner_id;
142     
143     	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "**** [%4.4s] Parsed **** Named_obj=%p Op=%p\n",
144     		&((acpi_namespace_node *)obj_handle)->name, obj_handle, op));
145     
146     	/* Install the parsed tree in the method object */
147     	/* TBD: [Restructure] Obsolete field? */
148     
149     	acpi_ps_delete_parse_tree (op);
150     
151     	return_ACPI_STATUS (status);
152     }
153     
154     
155     /*******************************************************************************
156      *
157      * FUNCTION:    Acpi_ds_begin_method_execution
158      *
159      * PARAMETERS:  Method_node         - Node of the method
160      *              Obj_desc            - The method object
161      *              Calling_method_node - Caller of this method (if non-null)
162      *
163      * RETURN:      Status
164      *
165      * DESCRIPTION: Prepare a method for execution.  Parses the method if necessary,
166      *              increments the thread count, and waits at the method semaphore
167      *              for clearance to execute.
168      *
169      * MUTEX:       Locks/unlocks parser.
170      *
171      ******************************************************************************/
172     
173     acpi_status
174     acpi_ds_begin_method_execution (
175     	acpi_namespace_node     *method_node,
176     	acpi_operand_object     *obj_desc,
177     	acpi_namespace_node     *calling_method_node)
178     {
179     	acpi_status             status = AE_OK;
180     
181     
182     	FUNCTION_TRACE_PTR ("Ds_begin_method_execution", method_node);
183     
184     
185     	if (!method_node) {
186     		return_ACPI_STATUS (AE_NULL_ENTRY);
187     	}
188     
189     
190     	/*
191     	 * If there is a concurrency limit on this method, we need to
192     	 * obtain a unit from the method semaphore.
193     	 */
194     	if (obj_desc->method.semaphore) {
195     		/*
196     		 * Allow recursive method calls, up to the reentrancy/concurrency
197     		 * limit imposed by the SERIALIZED rule and the Sync_level method
198     		 * parameter.
199     		 *
200     		 * The point of this code is to avoid permanently blocking a
201     		 * thread that is making recursive method calls.
202     		 */
203     		if (method_node == calling_method_node) {
204     			if (obj_desc->method.thread_count >= obj_desc->method.concurrency) {
205     				return_ACPI_STATUS (AE_AML_METHOD_LIMIT);
206     			}
207     		}
208     
209     		/*
210     		 * Get a unit from the method semaphore. This releases the
211     		 * interpreter if we block
212     		 */
213     		status = acpi_ex_system_wait_semaphore (obj_desc->method.semaphore,
214     				 WAIT_FOREVER);
215     	}
216     
217     
218     	/*
219     	 * Increment the method parse tree thread count since it has been
220     	 * reentered one more time (even if it is the same thread)
221     	 */
222     	obj_desc->method.thread_count++;
223     
224     	return_ACPI_STATUS (status);
225     }
226     
227     
228     /*******************************************************************************
229      *
230      * FUNCTION:    Acpi_ds_call_control_method
231      *
232      * PARAMETERS:  Walk_state          - Current state of the walk
233      *              Op                  - Current Op to be walked
234      *
235      * RETURN:      Status
236      *
237      * DESCRIPTION: Transfer execution to a called control method
238      *
239      ******************************************************************************/
240     
241     acpi_status
242     acpi_ds_call_control_method (
243     	acpi_walk_list          *walk_list,
244     	acpi_walk_state         *this_walk_state,
245     	acpi_parse_object       *op)
246     {
247     	acpi_status             status;
248     	acpi_namespace_node     *method_node;
249     	acpi_operand_object     *obj_desc;
250     	acpi_walk_state         *next_walk_state;
251     	acpi_parse_state        *parser_state;
252     	u32                     i;
253     
254     
255     	FUNCTION_TRACE_PTR ("Ds_call_control_method", this_walk_state);
256     
257     	ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Execute method %p, currentstate=%p\n",
258     		this_walk_state->prev_op, this_walk_state));
259     
260     	/*
261     	 * Get the namespace entry for the control method we are about to call
262     	 */
263     	method_node = this_walk_state->method_call_node;
264     	if (!method_node) {
265     		return_ACPI_STATUS (AE_NULL_ENTRY);
266     	}
267     
268     	obj_desc = acpi_ns_get_attached_object (method_node);
269     	if (!obj_desc) {
270     		return_ACPI_STATUS (AE_NULL_OBJECT);
271     	}
272     
273     
274     	/* Init for new method, wait on concurrency semaphore */
275     
276     	status = acpi_ds_begin_method_execution (method_node, obj_desc,
277     			  this_walk_state->method_node);
278     	if (ACPI_FAILURE (status)) {
279     		return_ACPI_STATUS (status);
280     	}
281     
282     	/* Create and initialize a new parser state */
283     
284     	parser_state = acpi_ps_create_state (obj_desc->method.pcode,
285     			   obj_desc->method.pcode_length);
286     	if (!parser_state) {
287     		return_ACPI_STATUS (AE_NO_MEMORY);
288     	}
289     
290     	acpi_ps_init_scope (parser_state, NULL);
291     	parser_state->start_node = method_node;
292     
293     
294     	/* Create a new state for the preempting walk */
295     
296     	next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id,
297     			  NULL, obj_desc, walk_list);
298     	if (!next_walk_state) {
299     		/* TBD: delete parser state */
300     
301     		return_ACPI_STATUS (AE_NO_MEMORY);
302     	}
303     
304     	next_walk_state->walk_type          = WALK_METHOD;
305     	next_walk_state->method_node        = method_node;
306     	next_walk_state->parser_state       = parser_state;
307     	next_walk_state->parse_flags        = this_walk_state->parse_flags;
308     	next_walk_state->descending_callback = this_walk_state->descending_callback;
309     	next_walk_state->ascending_callback = this_walk_state->ascending_callback;
310     
311     	/* The Next_op of the Next_walk will be the beginning of the method */
312     	/* TBD: [Restructure] -- obsolete? */
313     
314     	next_walk_state->next_op = NULL;
315     
316     	/* Open a new scope */
317     
318     	status = acpi_ds_scope_stack_push (method_node,
319     			   ACPI_TYPE_METHOD, next_walk_state);
320     	if (ACPI_FAILURE (status)) {
321     		goto cleanup;
322     	}
323     
324     
325     	/*
326     	 * Initialize the arguments for the method.  The resolved
327     	 * arguments were put on the previous walk state's operand
328     	 * stack.  Operands on the previous walk state stack always
329     	 * start at index 0.
330     	 */
331     	status = acpi_ds_method_data_init_args (&this_walk_state->operands[0],
332     			 this_walk_state->num_operands,
333     			 next_walk_state);
334     	if (ACPI_FAILURE (status)) {
335     		goto cleanup;
336     	}
337     
338     
339     	/* Create and init a Root Node */
340     
341     	op = acpi_ps_alloc_op (AML_SCOPE_OP);
342     	if (!op) {
343     		return_ACPI_STATUS (AE_NO_MEMORY);
344     	}
345     
346     	status = acpi_ps_parse_aml (op, obj_desc->method.pcode,
347     			  obj_desc->method.pcode_length,
348     			  ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE,
349     			  method_node, NULL, NULL,
350     			  acpi_ds_load1_begin_op, acpi_ds_load1_end_op);
351     	acpi_ps_delete_parse_tree (op);
352     
353     
354     	/*
355     	 * Delete the operands on the previous walkstate operand stack
356     	 * (they were copied to new objects)
357     	 */
358     	for (i = 0; i < obj_desc->method.param_count; i++) {
359     		acpi_ut_remove_reference (this_walk_state->operands [i]);
360     		this_walk_state->operands [i] = NULL;
361     	}
362     
363     	/* Clear the operand stack */
364     
365     	this_walk_state->num_operands = 0;
366     
367     
368     	ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Starting nested execution, newstate=%p\n",
369     		next_walk_state));
370     
371     	return_ACPI_STATUS (AE_OK);
372     
373     
374     	/* On error, we must delete the new walk state */
375     
376     cleanup:
377     	acpi_ds_terminate_control_method (next_walk_state);
378     	acpi_ds_delete_walk_state (next_walk_state);
379     	return_ACPI_STATUS (status);
380     
381     }
382     
383     
384     /*******************************************************************************
385      *
386      * FUNCTION:    Acpi_ds_restart_control_method
387      *
388      * PARAMETERS:  Walk_state          - State of the method when it was preempted
389      *              Op                  - Pointer to new current op
390      *
391      * RETURN:      Status
392      *
393      * DESCRIPTION: Restart a method that was preempted
394      *
395      ******************************************************************************/
396     
397     acpi_status
398     acpi_ds_restart_control_method (
399     	acpi_walk_state         *walk_state,
400     	acpi_operand_object     *return_desc)
401     {
402     	acpi_status             status;
403     
404     
405     	FUNCTION_TRACE_PTR ("Ds_restart_control_method", walk_state);
406     
407     
408     	if (return_desc) {
409     		if (walk_state->return_used) {
410     			/*
411     			 * Get the return value (if any) from the previous method.
412     			 * NULL if no return value
413     			 */
414     			status = acpi_ds_result_push (return_desc, walk_state);
415     			if (ACPI_FAILURE (status)) {
416     				acpi_ut_remove_reference (return_desc);
417     				return_ACPI_STATUS (status);
418     			}
419     		}
420     
421     		else {
422     			/*
423     			 * Delete the return value if it will not be used by the
424     			 * calling method
425     			 */
426     			acpi_ut_remove_reference (return_desc);
427     		}
428     
429     	}
430     
431     	ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
432     		"Method=%p Return=%p Return_used?=%X Res_stack=%p State=%p\n",
433     		walk_state->method_call_op, return_desc, walk_state->return_used,
434     		walk_state->results, walk_state));
435     
436     
437     	return_ACPI_STATUS (AE_OK);
438     }
439     
440     
441     /*******************************************************************************
442      *
443      * FUNCTION:    Acpi_ds_terminate_control_method
444      *
445      * PARAMETERS:  Walk_state          - State of the method
446      *
447      * RETURN:      Status
448      *
449      * DESCRIPTION: Terminate a control method.  Delete everything that the method
450      *              created, delete all locals and arguments, and delete the parse
451      *              tree if requested.
452      *
453      ******************************************************************************/
454     
455     acpi_status
456     acpi_ds_terminate_control_method (
457     	acpi_walk_state         *walk_state)
458     {
459     	acpi_operand_object     *obj_desc;
460     	acpi_namespace_node     *method_node;
461     
462     
463     	FUNCTION_TRACE_PTR ("Ds_terminate_control_method", walk_state);
464     
465     
466     	/* The method object should be stored in the walk state */
467     
468     	obj_desc = walk_state->method_desc;
469     	if (!obj_desc) {
470     		return_ACPI_STATUS (AE_OK);
471     	}
472     
473     	/* Delete all arguments and locals */
474     
475     	acpi_ds_method_data_delete_all (walk_state);
476     
477     	/*
478     	 * Lock the parser while we terminate this method.
479     	 * If this is the last thread executing the method,
480     	 * we have additional cleanup to perform
481     	 */
482     	acpi_ut_acquire_mutex (ACPI_MTX_PARSER);
483     
484     
485     	/* Signal completion of the execution of this method if necessary */
486     
487     	if (walk_state->method_desc->method.semaphore) {
488     		acpi_os_signal_semaphore (
489     			walk_state->method_desc->method.semaphore, 1);
490     	}
491     
492     	/* Decrement the thread count on the method parse tree */
493     
494     	walk_state->method_desc->method.thread_count--;
495     	if (!walk_state->method_desc->method.thread_count) {
496     		/*
497     		 * There are no more threads executing this method.  Perform
498     		 * additional cleanup.
499     		 *
500     		 * The method Node is stored in the walk state
501     		 */
502     		method_node = walk_state->method_node;
503     
504     		/*
505     		 * Delete any namespace entries created immediately underneath
506     		 * the method
507     		 */
508     		acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
509     		if (method_node->child) {
510     			acpi_ns_delete_namespace_subtree (method_node);
511     		}
512     
513     		/*
514     		 * Delete any namespace entries created anywhere else within
515     		 * the namespace
516     		 */
517     		acpi_ns_delete_namespace_by_owner (walk_state->method_desc->method.owning_id);
518     		acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
519     	}
520     
521     	acpi_ut_release_mutex (ACPI_MTX_PARSER);
522     	return_ACPI_STATUS (AE_OK);
523     }
524     
525     
526