[ACPI] acpi_register_gsi() fix needed for ACPICA 20051021
[linux-2.6-block.git] / drivers / acpi / dispatcher / dsmethod.c
CommitLineData
1da177e4
LT
1/******************************************************************************
2 *
3 * Module Name: dsmethod - Parser/Interpreter interface - control method parsing
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
1da177e4
LT
44#include <acpi/acpi.h>
45#include <acpi/acparser.h>
46#include <acpi/amlcode.h>
47#include <acpi/acdispat.h>
48#include <acpi/acinterp.h>
49#include <acpi/acnamesp.h>
50
1da177e4 51#define _COMPONENT ACPI_DISPATCHER
4be44fcd 52ACPI_MODULE_NAME("dsmethod")
1da177e4 53
1da177e4
LT
54/*******************************************************************************
55 *
56 * FUNCTION: acpi_ds_begin_method_execution
57 *
58 * PARAMETERS: method_node - Node of the method
59 * obj_desc - The method object
60 * calling_method_node - Caller of this method (if non-null)
61 *
62 * RETURN: Status
63 *
64 * DESCRIPTION: Prepare a method for execution. Parses the method if necessary,
65 * increments the thread count, and waits at the method semaphore
66 * for clearance to execute.
67 *
68 ******************************************************************************/
1da177e4 69acpi_status
4be44fcd
LB
70acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node,
71 union acpi_operand_object *obj_desc,
72 struct acpi_namespace_node *calling_method_node)
1da177e4 73{
4be44fcd 74 acpi_status status = AE_OK;
1da177e4 75
4be44fcd 76 ACPI_FUNCTION_TRACE_PTR("ds_begin_method_execution", method_node);
1da177e4
LT
77
78 if (!method_node) {
4be44fcd 79 return_ACPI_STATUS(AE_NULL_ENTRY);
1da177e4
LT
80 }
81
aff8c277
RM
82 /* Prevent wraparound of thread count */
83
84 if (obj_desc->method.thread_count == ACPI_UINT8_MAX) {
85 ACPI_REPORT_ERROR(("Method reached maximum reentrancy limit (255)\n"));
86 return_ACPI_STATUS(AE_AML_METHOD_LIMIT);
87 }
88
1da177e4
LT
89 /*
90 * If there is a concurrency limit on this method, we need to
91 * obtain a unit from the method semaphore.
92 */
93 if (obj_desc->method.semaphore) {
94 /*
95 * Allow recursive method calls, up to the reentrancy/concurrency
96 * limit imposed by the SERIALIZED rule and the sync_level method
97 * parameter.
98 *
99 * The point of this code is to avoid permanently blocking a
100 * thread that is making recursive method calls.
101 */
102 if (method_node == calling_method_node) {
4be44fcd
LB
103 if (obj_desc->method.thread_count >=
104 obj_desc->method.concurrency) {
105 return_ACPI_STATUS(AE_AML_METHOD_LIMIT);
1da177e4
LT
106 }
107 }
108
109 /*
110 * Get a unit from the method semaphore. This releases the
111 * interpreter if we block
112 */
4be44fcd
LB
113 status =
114 acpi_ex_system_wait_semaphore(obj_desc->method.semaphore,
115 ACPI_WAIT_FOREVER);
1da177e4
LT
116 }
117
aff8c277
RM
118 /*
119 * Allocate an Owner ID for this method, only if this is the first thread
120 * to begin concurrent execution. We only need one owner_id, even if the
121 * method is invoked recursively.
122 */
123 if (!obj_desc->method.owner_id) {
124 status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id);
125 if (ACPI_FAILURE(status)) {
126 return_ACPI_STATUS(status);
127 }
128 }
129
1da177e4
LT
130 /*
131 * Increment the method parse tree thread count since it has been
132 * reentered one more time (even if it is the same thread)
133 */
134 obj_desc->method.thread_count++;
4be44fcd 135 return_ACPI_STATUS(status);
1da177e4
LT
136}
137
1da177e4
LT
138/*******************************************************************************
139 *
140 * FUNCTION: acpi_ds_call_control_method
141 *
142 * PARAMETERS: Thread - Info for this thread
143 * this_walk_state - Current walk state
144 * Op - Current Op to be walked
145 *
146 * RETURN: Status
147 *
148 * DESCRIPTION: Transfer execution to a called control method
149 *
150 ******************************************************************************/
151
152acpi_status
4be44fcd
LB
153acpi_ds_call_control_method(struct acpi_thread_state *thread,
154 struct acpi_walk_state *this_walk_state,
155 union acpi_parse_object *op)
1da177e4 156{
4be44fcd
LB
157 acpi_status status;
158 struct acpi_namespace_node *method_node;
159 struct acpi_walk_state *next_walk_state = NULL;
160 union acpi_operand_object *obj_desc;
161 struct acpi_parameter_info info;
162 u32 i;
1da177e4 163
4be44fcd 164 ACPI_FUNCTION_TRACE_PTR("ds_call_control_method", this_walk_state);
1da177e4 165
4be44fcd
LB
166 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
167 "Execute method %p, currentstate=%p\n",
168 this_walk_state->prev_op, this_walk_state));
1da177e4
LT
169
170 /*
171 * Get the namespace entry for the control method we are about to call
172 */
173 method_node = this_walk_state->method_call_node;
174 if (!method_node) {
4be44fcd 175 return_ACPI_STATUS(AE_NULL_ENTRY);
1da177e4
LT
176 }
177
4be44fcd 178 obj_desc = acpi_ns_get_attached_object(method_node);
1da177e4 179 if (!obj_desc) {
4be44fcd 180 return_ACPI_STATUS(AE_NULL_OBJECT);
1da177e4
LT
181 }
182
1da177e4
LT
183 /* Init for new method, wait on concurrency semaphore */
184
4be44fcd
LB
185 status = acpi_ds_begin_method_execution(method_node, obj_desc,
186 this_walk_state->method_node);
187 if (ACPI_FAILURE(status)) {
f9f4601f 188 goto cleanup;
1da177e4
LT
189 }
190
191 if (!(obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY)) {
192 /* 1) Parse: Create a new walk state for the preempting walk */
193
4be44fcd
LB
194 next_walk_state =
195 acpi_ds_create_walk_state(obj_desc->method.owner_id, op,
196 obj_desc, NULL);
1da177e4 197 if (!next_walk_state) {
4be44fcd 198 return_ACPI_STATUS(AE_NO_MEMORY);
1da177e4
LT
199 }
200
201 /* Create and init a Root Node */
202
4be44fcd 203 op = acpi_ps_create_scope_op();
1da177e4
LT
204 if (!op) {
205 status = AE_NO_MEMORY;
206 goto cleanup;
207 }
208
4be44fcd
LB
209 status = acpi_ds_init_aml_walk(next_walk_state, op, method_node,
210 obj_desc->method.aml_start,
211 obj_desc->method.aml_length,
212 NULL, 1);
213 if (ACPI_FAILURE(status)) {
214 acpi_ds_delete_walk_state(next_walk_state);
1da177e4
LT
215 goto cleanup;
216 }
217
218 /* Begin AML parse */
219
4be44fcd
LB
220 status = acpi_ps_parse_aml(next_walk_state);
221 acpi_ps_delete_parse_tree(op);
1da177e4
LT
222 }
223
224 /* 2) Execute: Create a new state for the preempting walk */
225
4be44fcd
LB
226 next_walk_state = acpi_ds_create_walk_state(obj_desc->method.owner_id,
227 NULL, obj_desc, thread);
1da177e4
LT
228 if (!next_walk_state) {
229 status = AE_NO_MEMORY;
230 goto cleanup;
231 }
232 /*
233 * The resolved arguments were put on the previous walk state's operand
aff8c277
RM
234 * stack. Operands on the previous walk state stack always
235 * start at index 0. Also, null terminate the list of arguments
1da177e4 236 */
4be44fcd 237 this_walk_state->operands[this_walk_state->num_operands] = NULL;
1da177e4
LT
238
239 info.parameters = &this_walk_state->operands[0];
240 info.parameter_type = ACPI_PARAM_ARGS;
241
4be44fcd
LB
242 status = acpi_ds_init_aml_walk(next_walk_state, NULL, method_node,
243 obj_desc->method.aml_start,
244 obj_desc->method.aml_length, &info, 3);
245 if (ACPI_FAILURE(status)) {
1da177e4
LT
246 goto cleanup;
247 }
248
249 /*
250 * Delete the operands on the previous walkstate operand stack
251 * (they were copied to new objects)
252 */
253 for (i = 0; i < obj_desc->method.param_count; i++) {
4be44fcd
LB
254 acpi_ut_remove_reference(this_walk_state->operands[i]);
255 this_walk_state->operands[i] = NULL;
1da177e4
LT
256 }
257
258 /* Clear the operand stack */
259
260 this_walk_state->num_operands = 0;
261
4be44fcd
LB
262 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
263 "Starting nested execution, newstate=%p\n",
264 next_walk_state));
1da177e4
LT
265
266 if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) {
4be44fcd 267 status = obj_desc->method.implementation(next_walk_state);
1da177e4
LT
268 }
269
aff8c277 270 return_ACPI_STATUS(status);
a94f1881
LB
271
272 cleanup:
aff8c277 273 /* Decrement the thread count on the method parse tree */
a94f1881 274
aff8c277 275 if (next_walk_state && (next_walk_state->method_desc)) {
4be44fcd 276 next_walk_state->method_desc->method.thread_count--;
1da177e4 277 }
aff8c277
RM
278
279 /* On error, we must delete the new walk state */
280
281 acpi_ds_terminate_control_method(next_walk_state);
a94f1881 282 acpi_ds_delete_walk_state(next_walk_state);
4be44fcd 283 return_ACPI_STATUS(status);
1da177e4
LT
284}
285
1da177e4
LT
286/*******************************************************************************
287 *
288 * FUNCTION: acpi_ds_restart_control_method
289 *
290 * PARAMETERS: walk_state - State for preempted method (caller)
291 * return_desc - Return value from the called method
292 *
293 * RETURN: Status
294 *
295 * DESCRIPTION: Restart a method that was preempted by another (nested) method
296 * invocation. Handle the return value (if any) from the callee.
297 *
298 ******************************************************************************/
299
300acpi_status
4be44fcd
LB
301acpi_ds_restart_control_method(struct acpi_walk_state *walk_state,
302 union acpi_operand_object *return_desc)
1da177e4 303{
4be44fcd 304 acpi_status status;
1da177e4 305
4be44fcd 306 ACPI_FUNCTION_TRACE_PTR("ds_restart_control_method", walk_state);
1da177e4 307
4be44fcd
LB
308 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
309 "****Restart [%4.4s] Op %p return_value_from_callee %p\n",
310 (char *)&walk_state->method_node->name,
311 walk_state->method_call_op, return_desc));
1da177e4 312
4be44fcd
LB
313 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
314 " return_from_this_method_used?=%X res_stack %p Walk %p\n",
315 walk_state->return_used,
316 walk_state->results, walk_state));
1da177e4
LT
317
318 /* Did the called method return a value? */
319
320 if (return_desc) {
321 /* Are we actually going to use the return value? */
322
323 if (walk_state->return_used) {
324 /* Save the return value from the previous method */
325
4be44fcd
LB
326 status = acpi_ds_result_push(return_desc, walk_state);
327 if (ACPI_FAILURE(status)) {
328 acpi_ut_remove_reference(return_desc);
329 return_ACPI_STATUS(status);
1da177e4
LT
330 }
331
332 /*
333 * Save as THIS method's return value in case it is returned
334 * immediately to yet another method
335 */
336 walk_state->return_desc = return_desc;
337 }
338
339 /*
340 * The following code is the
341 * optional support for a so-called "implicit return". Some AML code
342 * assumes that the last value of the method is "implicitly" returned
343 * to the caller. Just save the last result as the return value.
344 * NOTE: this is optional because the ASL language does not actually
345 * support this behavior.
346 */
4be44fcd
LB
347 else if (!acpi_ds_do_implicit_return
348 (return_desc, walk_state, FALSE)) {
1da177e4
LT
349 /*
350 * Delete the return value if it will not be used by the
351 * calling method
352 */
4be44fcd 353 acpi_ut_remove_reference(return_desc);
1da177e4
LT
354 }
355 }
356
4be44fcd 357 return_ACPI_STATUS(AE_OK);
1da177e4
LT
358}
359
1da177e4
LT
360/*******************************************************************************
361 *
362 * FUNCTION: acpi_ds_terminate_control_method
363 *
364 * PARAMETERS: walk_state - State of the method
365 *
aff8c277 366 * RETURN: None
1da177e4
LT
367 *
368 * DESCRIPTION: Terminate a control method. Delete everything that the method
369 * created, delete all locals and arguments, and delete the parse
370 * tree if requested.
371 *
372 ******************************************************************************/
373
aff8c277 374void acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state)
1da177e4 375{
4be44fcd
LB
376 union acpi_operand_object *obj_desc;
377 struct acpi_namespace_node *method_node;
378 acpi_status status;
1da177e4 379
4be44fcd 380 ACPI_FUNCTION_TRACE_PTR("ds_terminate_control_method", walk_state);
1da177e4
LT
381
382 if (!walk_state) {
aff8c277 383 return_VOID;
1da177e4
LT
384 }
385
386 /* The current method object was saved in the walk state */
387
388 obj_desc = walk_state->method_desc;
389 if (!obj_desc) {
aff8c277 390 return_VOID;
1da177e4
LT
391 }
392
393 /* Delete all arguments and locals */
394
4be44fcd 395 acpi_ds_method_data_delete_all(walk_state);
1da177e4
LT
396
397 /*
398 * Lock the parser while we terminate this method.
399 * If this is the last thread executing the method,
400 * we have additional cleanup to perform
401 */
4be44fcd
LB
402 status = acpi_ut_acquire_mutex(ACPI_MTX_PARSER);
403 if (ACPI_FAILURE(status)) {
aff8c277 404 return_VOID;
1da177e4
LT
405 }
406
407 /* Signal completion of the execution of this method if necessary */
408
409 if (walk_state->method_desc->method.semaphore) {
4be44fcd
LB
410 status =
411 acpi_os_signal_semaphore(walk_state->method_desc->method.
412 semaphore, 1);
413 if (ACPI_FAILURE(status)) {
414 ACPI_REPORT_ERROR(("Could not signal method semaphore\n"));
1da177e4
LT
415
416 /* Ignore error and continue cleanup */
417 }
418 }
419
28f55ebc
BM
420 /*
421 * There are no more threads executing this method. Perform
422 * additional cleanup.
423 *
424 * The method Node is stored in the walk state
425 */
426 method_node = walk_state->method_node;
427
428 /* Lock namespace for possible update */
429
430 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
431 if (ACPI_FAILURE(status)) {
432 goto exit;
433 }
434
435 /*
436 * Delete any namespace entries created immediately underneath
437 * the method
438 */
439 if (method_node->child) {
440 acpi_ns_delete_namespace_subtree(method_node);
441 }
442
443 /*
444 * Delete any namespace entries created anywhere else within
445 * the namespace by the execution of this method
446 */
447 acpi_ns_delete_namespace_by_owner(walk_state->method_desc->method.
448 owner_id);
449 status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
450
451 /* Are there any other threads currently executing this method? */
452
1da177e4 453 if (walk_state->method_desc->method.thread_count) {
28f55ebc
BM
454 /*
455 * Additional threads. Do not release the owner_id in this case,
456 * we immediately reuse it for the next thread executing this method
457 */
4be44fcd 458 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
28f55ebc 459 "*** Completed execution of one thread, %d threads remaining\n",
4be44fcd
LB
460 walk_state->method_desc->method.
461 thread_count));
28f55ebc
BM
462 } else {
463 /* This is the only executing thread for this method */
1da177e4 464
1da177e4
LT
465 /*
466 * Support to dynamically change a method from not_serialized to
28f55ebc 467 * Serialized if it appears that the method is incorrectly written and
1da177e4
LT
468 * does not support multiple thread execution. The best example of this
469 * is if such a method creates namespace objects and blocks. A second
470 * thread will fail with an AE_ALREADY_EXISTS exception
471 *
472 * This code is here because we must wait until the last thread exits
473 * before creating the synchronization semaphore.
474 */
475 if ((walk_state->method_desc->method.concurrency == 1) &&
4be44fcd
LB
476 (!walk_state->method_desc->method.semaphore)) {
477 status = acpi_os_create_semaphore(1, 1,
478 &walk_state->
479 method_desc->method.
480 semaphore);
1da177e4
LT
481 }
482
28f55ebc 483 /* No more threads, we can free the owner_id */
1da177e4 484
4be44fcd
LB
485 acpi_ut_release_owner_id(&walk_state->method_desc->method.
486 owner_id);
1da177e4 487 }
a94f1881 488
aff8c277
RM
489 exit:
490 (void)acpi_ut_release_mutex(ACPI_MTX_PARSER);
491 return_VOID;
1da177e4 492}
28f55ebc
BM
493
494#ifdef ACPI_INIT_PARSE_METHODS
495 /*
496 * Note 11/2005: Removed this code to parse all methods during table
497 * load because it causes problems if there are any errors during the
498 * parse. Also, it seems like overkill and we probably don't want to
499 * abort a table load because of an issue with a single method.
500 */
501
502/*******************************************************************************
503 *
504 * FUNCTION: acpi_ds_parse_method
505 *
506 * PARAMETERS: Node - Method node
507 *
508 * RETURN: Status
509 *
510 * DESCRIPTION: Parse the AML that is associated with the method.
511 *
512 * MUTEX: Assumes parser is locked
513 *
514 ******************************************************************************/
515
516acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node)
517{
518 acpi_status status;
519 union acpi_operand_object *obj_desc;
520 union acpi_parse_object *op;
521 struct acpi_walk_state *walk_state;
522
523 ACPI_FUNCTION_TRACE_PTR("ds_parse_method", node);
524
525 /* Parameter Validation */
526
527 if (!node) {
528 return_ACPI_STATUS(AE_NULL_ENTRY);
529 }
530
531 ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
532 "**** Parsing [%4.4s] **** named_obj=%p\n",
533 acpi_ut_get_node_name(node), node));
534
535 /* Extract the method object from the method Node */
536
537 obj_desc = acpi_ns_get_attached_object(node);
538 if (!obj_desc) {
539 return_ACPI_STATUS(AE_NULL_OBJECT);
540 }
541
542 /* Create a mutex for the method if there is a concurrency limit */
543
544 if ((obj_desc->method.concurrency != ACPI_INFINITE_CONCURRENCY) &&
545 (!obj_desc->method.semaphore)) {
546 status = acpi_os_create_semaphore(obj_desc->method.concurrency,
547 obj_desc->method.concurrency,
548 &obj_desc->method.semaphore);
549 if (ACPI_FAILURE(status)) {
550 return_ACPI_STATUS(status);
551 }
552 }
553
554 /*
555 * Allocate a new parser op to be the root of the parsed
556 * method tree
557 */
558 op = acpi_ps_alloc_op(AML_METHOD_OP);
559 if (!op) {
560 return_ACPI_STATUS(AE_NO_MEMORY);
561 }
562
563 /* Init new op with the method name and pointer back to the Node */
564
565 acpi_ps_set_name(op, node->name.integer);
566 op->common.node = node;
567
568 /*
569 * Get a new owner_id for objects created by this method. Namespace
570 * objects (such as Operation Regions) can be created during the
571 * first pass parse.
572 */
573 status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id);
574 if (ACPI_FAILURE(status)) {
575 goto cleanup;
576 }
577
578 /* Create and initialize a new walk state */
579
580 walk_state =
581 acpi_ds_create_walk_state(obj_desc->method.owner_id, NULL, NULL,
582 NULL);
583 if (!walk_state) {
584 status = AE_NO_MEMORY;
585 goto cleanup2;
586 }
587
588 status = acpi_ds_init_aml_walk(walk_state, op, node,
589 obj_desc->method.aml_start,
590 obj_desc->method.aml_length, NULL, 1);
591 if (ACPI_FAILURE(status)) {
592 acpi_ds_delete_walk_state(walk_state);
593 goto cleanup2;
594 }
595
596 /*
597 * Parse the method, first pass
598 *
599 * The first pass load is where newly declared named objects are added into
600 * the namespace. Actual evaluation of the named objects (what would be
601 * called a "second pass") happens during the actual execution of the
602 * method so that operands to the named objects can take on dynamic
603 * run-time values.
604 */
605 status = acpi_ps_parse_aml(walk_state);
606 if (ACPI_FAILURE(status)) {
607 goto cleanup2;
608 }
609
610 ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
611 "**** [%4.4s] Parsed **** named_obj=%p Op=%p\n",
612 acpi_ut_get_node_name(node), node, op));
613
614 /*
615 * Delete the parse tree. We simply re-parse the method for every
616 * execution since there isn't much overhead (compared to keeping lots
617 * of parse trees around)
618 */
619 acpi_ns_delete_namespace_subtree(node);
620 acpi_ns_delete_namespace_by_owner(obj_desc->method.owner_id);
621
622 cleanup2:
623 acpi_ut_release_owner_id(&obj_desc->method.owner_id);
624
625 cleanup:
626 acpi_ps_delete_parse_tree(op);
627 return_ACPI_STATUS(status);
628}
629#endif