aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/dispatcher/dsmethod.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/dispatcher/dsmethod.c')
-rw-r--r--drivers/acpi/dispatcher/dsmethod.c180
1 files changed, 102 insertions, 78 deletions
diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c
index 7dc59fc7344f..651f2b68531b 100644
--- a/drivers/acpi/dispatcher/dsmethod.c
+++ b/drivers/acpi/dispatcher/dsmethod.c
@@ -134,7 +134,7 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node * method_node,
134{ 134{
135 acpi_status status = AE_OK; 135 acpi_status status = AE_OK;
136 136
137 ACPI_FUNCTION_TRACE_PTR("ds_begin_method_execution", method_node); 137 ACPI_FUNCTION_TRACE_PTR(ds_begin_method_execution, method_node);
138 138
139 if (!method_node) { 139 if (!method_node) {
140 return_ACPI_STATUS(AE_NULL_ENTRY); 140 return_ACPI_STATUS(AE_NULL_ENTRY);
@@ -170,11 +170,14 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node * method_node,
170 170
171 /* 171 /*
172 * Get a unit from the method semaphore. This releases the 172 * Get a unit from the method semaphore. This releases the
173 * interpreter if we block 173 * interpreter if we block (then reacquires it)
174 */ 174 */
175 status = 175 status =
176 acpi_ex_system_wait_semaphore(obj_desc->method.semaphore, 176 acpi_ex_system_wait_semaphore(obj_desc->method.semaphore,
177 ACPI_WAIT_FOREVER); 177 ACPI_WAIT_FOREVER);
178 if (ACPI_FAILURE(status)) {
179 return_ACPI_STATUS(status);
180 }
178 } 181 }
179 182
180 /* 183 /*
@@ -185,7 +188,7 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node * method_node,
185 if (!obj_desc->method.owner_id) { 188 if (!obj_desc->method.owner_id) {
186 status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id); 189 status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id);
187 if (ACPI_FAILURE(status)) { 190 if (ACPI_FAILURE(status)) {
188 return_ACPI_STATUS(status); 191 goto cleanup;
189 } 192 }
190 } 193 }
191 194
@@ -195,6 +198,14 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node * method_node,
195 */ 198 */
196 obj_desc->method.thread_count++; 199 obj_desc->method.thread_count++;
197 return_ACPI_STATUS(status); 200 return_ACPI_STATUS(status);
201
202 cleanup:
203 /* On error, must signal the method semaphore if present */
204
205 if (obj_desc->method.semaphore) {
206 (void)acpi_os_signal_semaphore(obj_desc->method.semaphore, 1);
207 }
208 return_ACPI_STATUS(status);
198} 209}
199 210
200/******************************************************************************* 211/*******************************************************************************
@@ -223,7 +234,7 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread,
223 struct acpi_parameter_info info; 234 struct acpi_parameter_info info;
224 u32 i; 235 u32 i;
225 236
226 ACPI_FUNCTION_TRACE_PTR("ds_call_control_method", this_walk_state); 237 ACPI_FUNCTION_TRACE_PTR(ds_call_control_method, this_walk_state);
227 238
228 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, 239 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
229 "Execute method %p, currentstate=%p\n", 240 "Execute method %p, currentstate=%p\n",
@@ -242,26 +253,31 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread,
242 return_ACPI_STATUS(AE_NULL_OBJECT); 253 return_ACPI_STATUS(AE_NULL_OBJECT);
243 } 254 }
244 255
245 /* Init for new method, wait on concurrency semaphore */ 256 /* Init for new method, possibly wait on concurrency semaphore */
246 257
247 status = acpi_ds_begin_method_execution(method_node, obj_desc, 258 status = acpi_ds_begin_method_execution(method_node, obj_desc,
248 this_walk_state->method_node); 259 this_walk_state->method_node);
249 if (ACPI_FAILURE(status)) { 260 if (ACPI_FAILURE(status)) {
250 goto cleanup; 261 return_ACPI_STATUS(status);
251 } 262 }
252 263
264 /*
265 * 1) Parse the method. All "normal" methods are parsed for each execution.
266 * Internal methods (_OSI, etc.) do not require parsing.
267 */
253 if (!(obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY)) { 268 if (!(obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY)) {
254 269
255 /* 1) Parse: Create a new walk state for the preempting walk */ 270 /* Create a new walk state for the parse */
256 271
257 next_walk_state = 272 next_walk_state =
258 acpi_ds_create_walk_state(obj_desc->method.owner_id, op, 273 acpi_ds_create_walk_state(obj_desc->method.owner_id, op,
259 obj_desc, NULL); 274 obj_desc, NULL);
260 if (!next_walk_state) { 275 if (!next_walk_state) {
261 return_ACPI_STATUS(AE_NO_MEMORY); 276 status = AE_NO_MEMORY;
277 goto cleanup;
262 } 278 }
263 279
264 /* Create and init a Root Node */ 280 /* Create and init a parse tree root */
265 281
266 op = acpi_ps_create_scope_op(); 282 op = acpi_ps_create_scope_op();
267 if (!op) { 283 if (!op) {
@@ -274,17 +290,20 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread,
274 obj_desc->method.aml_length, 290 obj_desc->method.aml_length,
275 NULL, 1); 291 NULL, 1);
276 if (ACPI_FAILURE(status)) { 292 if (ACPI_FAILURE(status)) {
277 acpi_ds_delete_walk_state(next_walk_state); 293 acpi_ps_delete_parse_tree(op);
278 goto cleanup; 294 goto cleanup;
279 } 295 }
280 296
281 /* Begin AML parse */ 297 /* Begin AML parse (deletes next_walk_state) */
282 298
283 status = acpi_ps_parse_aml(next_walk_state); 299 status = acpi_ps_parse_aml(next_walk_state);
284 acpi_ps_delete_parse_tree(op); 300 acpi_ps_delete_parse_tree(op);
301 if (ACPI_FAILURE(status)) {
302 goto cleanup;
303 }
285 } 304 }
286 305
287 /* 2) Execute: Create a new state for the preempting walk */ 306 /* 2) Begin method execution. Create a new walk state */
288 307
289 next_walk_state = acpi_ds_create_walk_state(obj_desc->method.owner_id, 308 next_walk_state = acpi_ds_create_walk_state(obj_desc->method.owner_id,
290 NULL, obj_desc, thread); 309 NULL, obj_desc, thread);
@@ -292,6 +311,7 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread,
292 status = AE_NO_MEMORY; 311 status = AE_NO_MEMORY;
293 goto cleanup; 312 goto cleanup;
294 } 313 }
314
295 /* 315 /*
296 * The resolved arguments were put on the previous walk state's operand 316 * The resolved arguments were put on the previous walk state's operand
297 * stack. Operands on the previous walk state stack always 317 * stack. Operands on the previous walk state stack always
@@ -326,6 +346,8 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread,
326 "Starting nested execution, newstate=%p\n", 346 "Starting nested execution, newstate=%p\n",
327 next_walk_state)); 347 next_walk_state));
328 348
349 /* Invoke an internal method if necessary */
350
329 if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) { 351 if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) {
330 status = obj_desc->method.implementation(next_walk_state); 352 status = obj_desc->method.implementation(next_walk_state);
331 } 353 }
@@ -333,16 +355,14 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread,
333 return_ACPI_STATUS(status); 355 return_ACPI_STATUS(status);
334 356
335 cleanup: 357 cleanup:
336 /* Decrement the thread count on the method parse tree */
337 358
338 if (next_walk_state && (next_walk_state->method_desc)) { 359 /* On error, we must terminate the method properly */
339 next_walk_state->method_desc->method.thread_count--;
340 }
341 360
342 /* On error, we must delete the new walk state */ 361 acpi_ds_terminate_control_method(obj_desc, next_walk_state);
362 if (next_walk_state) {
363 acpi_ds_delete_walk_state(next_walk_state);
364 }
343 365
344 acpi_ds_terminate_control_method(next_walk_state);
345 acpi_ds_delete_walk_state(next_walk_state);
346 return_ACPI_STATUS(status); 366 return_ACPI_STATUS(status);
347} 367}
348 368
@@ -366,15 +386,15 @@ acpi_ds_restart_control_method(struct acpi_walk_state *walk_state,
366{ 386{
367 acpi_status status; 387 acpi_status status;
368 388
369 ACPI_FUNCTION_TRACE_PTR("ds_restart_control_method", walk_state); 389 ACPI_FUNCTION_TRACE_PTR(ds_restart_control_method, walk_state);
370 390
371 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, 391 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
372 "****Restart [%4.4s] Op %p return_value_from_callee %p\n", 392 "****Restart [%4.4s] Op %p ReturnValueFromCallee %p\n",
373 (char *)&walk_state->method_node->name, 393 (char *)&walk_state->method_node->name,
374 walk_state->method_call_op, return_desc)); 394 walk_state->method_call_op, return_desc));
375 395
376 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, 396 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
377 " return_from_this_method_used?=%X res_stack %p Walk %p\n", 397 " ReturnFromThisMethodUsed?=%X ResStack %p Walk %p\n",
378 walk_state->return_used, 398 walk_state->return_used,
379 walk_state->results, walk_state)); 399 walk_state->results, walk_state));
380 400
@@ -426,7 +446,8 @@ acpi_ds_restart_control_method(struct acpi_walk_state *walk_state,
426 * 446 *
427 * FUNCTION: acpi_ds_terminate_control_method 447 * FUNCTION: acpi_ds_terminate_control_method
428 * 448 *
429 * PARAMETERS: walk_state - State of the method 449 * PARAMETERS: method_desc - Method object
450 * walk_state - State associated with the method
430 * 451 *
431 * RETURN: None 452 * RETURN: None
432 * 453 *
@@ -436,28 +457,27 @@ acpi_ds_restart_control_method(struct acpi_walk_state *walk_state,
436 * 457 *
437 ******************************************************************************/ 458 ******************************************************************************/
438 459
439void acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state) 460void
461acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
462 struct acpi_walk_state *walk_state)
440{ 463{
441 union acpi_operand_object *obj_desc;
442 struct acpi_namespace_node *method_node; 464 struct acpi_namespace_node *method_node;
443 acpi_status status; 465 acpi_status status;
444 466
445 ACPI_FUNCTION_TRACE_PTR("ds_terminate_control_method", walk_state); 467 ACPI_FUNCTION_TRACE_PTR(ds_terminate_control_method, walk_state);
446
447 if (!walk_state) {
448 return_VOID;
449 }
450 468
451 /* The current method object was saved in the walk state */ 469 /* method_desc is required, walk_state is optional */
452 470
453 obj_desc = walk_state->method_desc; 471 if (!method_desc) {
454 if (!obj_desc) {
455 return_VOID; 472 return_VOID;
456 } 473 }
457 474
458 /* Delete all arguments and locals */ 475 if (walk_state) {
459 476
460 acpi_ds_method_data_delete_all(walk_state); 477 /* Delete all arguments and locals */
478
479 acpi_ds_method_data_delete_all(walk_state);
480 }
461 481
462 /* 482 /*
463 * Lock the parser while we terminate this method. 483 * Lock the parser while we terminate this method.
@@ -471,60 +491,66 @@ void acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state)
471 491
472 /* Signal completion of the execution of this method if necessary */ 492 /* Signal completion of the execution of this method if necessary */
473 493
474 if (walk_state->method_desc->method.semaphore) { 494 if (method_desc->method.semaphore) {
475 status = 495 status =
476 acpi_os_signal_semaphore(walk_state->method_desc->method. 496 acpi_os_signal_semaphore(method_desc->method.semaphore, 1);
477 semaphore, 1);
478 if (ACPI_FAILURE(status)) { 497 if (ACPI_FAILURE(status)) {
479 ACPI_ERROR((AE_INFO,
480 "Could not signal method semaphore"));
481 498
482 /* Ignore error and continue cleanup */ 499 /* Ignore error and continue */
500
501 ACPI_EXCEPTION((AE_INFO, status,
502 "Could not signal method semaphore"));
483 } 503 }
484 } 504 }
485 505
486 /* 506 if (walk_state) {
487 * There are no more threads executing this method. Perform 507 /*
488 * additional cleanup. 508 * Delete any objects created by this method during execution.
489 * 509 * The method Node is stored in the walk state
490 * The method Node is stored in the walk state 510 */
491 */ 511 method_node = walk_state->method_node;
492 method_node = walk_state->method_node;
493 512
494 /* Lock namespace for possible update */ 513 /* Lock namespace for possible update */
495 514
496 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 515 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
497 if (ACPI_FAILURE(status)) { 516 if (ACPI_FAILURE(status)) {
498 goto exit; 517 goto exit;
499 } 518 }
500 519
501 /* 520 /*
502 * Delete any namespace entries created immediately underneath 521 * Delete any namespace entries created immediately underneath
503 * the method 522 * the method
504 */ 523 */
505 if (method_node && method_node->child) { 524 if (method_node && method_node->child) {
506 acpi_ns_delete_namespace_subtree(method_node); 525 acpi_ns_delete_namespace_subtree(method_node);
526 }
527
528 /*
529 * Delete any namespace entries created anywhere else within
530 * the namespace by the execution of this method
531 */
532 acpi_ns_delete_namespace_by_owner(method_desc->method.owner_id);
533 status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
507 } 534 }
508 535
509 /* 536 /* Decrement the thread count on the method */
510 * Delete any namespace entries created anywhere else within 537
511 * the namespace by the execution of this method 538 if (method_desc->method.thread_count) {
512 */ 539 method_desc->method.thread_count--;
513 acpi_ns_delete_namespace_by_owner(walk_state->method_desc->method. 540 } else {
514 owner_id); 541 ACPI_ERROR((AE_INFO, "Invalid zero thread count in method"));
515 status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 542 }
516 543
517 /* Are there any other threads currently executing this method? */ 544 /* Are there any other threads currently executing this method? */
518 545
519 if (walk_state->method_desc->method.thread_count) { 546 if (method_desc->method.thread_count) {
520 /* 547 /*
521 * Additional threads. Do not release the owner_id in this case, 548 * Additional threads. Do not release the owner_id in this case,
522 * we immediately reuse it for the next thread executing this method 549 * we immediately reuse it for the next thread executing this method
523 */ 550 */
524 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, 551 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
525 "*** Completed execution of one thread, %d threads remaining\n", 552 "*** Completed execution of one thread, %d threads remaining\n",
526 walk_state->method_desc->method. 553 method_desc->method.thread_count));
527 thread_count));
528 } else { 554 } else {
529 /* This is the only executing thread for this method */ 555 /* This is the only executing thread for this method */
530 556
@@ -538,18 +564,16 @@ void acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state)
538 * This code is here because we must wait until the last thread exits 564 * This code is here because we must wait until the last thread exits
539 * before creating the synchronization semaphore. 565 * before creating the synchronization semaphore.
540 */ 566 */
541 if ((walk_state->method_desc->method.concurrency == 1) && 567 if ((method_desc->method.concurrency == 1) &&
542 (!walk_state->method_desc->method.semaphore)) { 568 (!method_desc->method.semaphore)) {
543 status = acpi_os_create_semaphore(1, 1, 569 status = acpi_os_create_semaphore(1, 1,
544 &walk_state-> 570 &method_desc->method.
545 method_desc->method.
546 semaphore); 571 semaphore);
547 } 572 }
548 573
549 /* No more threads, we can free the owner_id */ 574 /* No more threads, we can free the owner_id */
550 575
551 acpi_ut_release_owner_id(&walk_state->method_desc->method. 576 acpi_ut_release_owner_id(&method_desc->method.owner_id);
552 owner_id);
553 } 577 }
554 578
555 exit: 579 exit:
@@ -586,7 +610,7 @@ acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node)
586 union acpi_parse_object *op; 610 union acpi_parse_object *op;
587 struct acpi_walk_state *walk_state; 611 struct acpi_walk_state *walk_state;
588 612
589 ACPI_FUNCTION_TRACE_PTR("ds_parse_method", node); 613 ACPI_FUNCTION_TRACE_PTR(ds_parse_method, node);
590 614
591 /* Parameter Validation */ 615 /* Parameter Validation */
592 616
@@ -595,7 +619,7 @@ acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node)
595 } 619 }
596 620
597 ACPI_DEBUG_PRINT((ACPI_DB_PARSE, 621 ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
598 "**** Parsing [%4.4s] **** named_obj=%p\n", 622 "**** Parsing [%4.4s] **** NamedObj=%p\n",
599 acpi_ut_get_node_name(node), node)); 623 acpi_ut_get_node_name(node), node));
600 624
601 /* Extract the method object from the method Node */ 625 /* Extract the method object from the method Node */
@@ -674,7 +698,7 @@ acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node)
674 } 698 }
675 699
676 ACPI_DEBUG_PRINT((ACPI_DB_PARSE, 700 ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
677 "**** [%4.4s] Parsed **** named_obj=%p Op=%p\n", 701 "**** [%4.4s] Parsed **** NamedObj=%p Op=%p\n",
678 acpi_ut_get_node_name(node), node, op)); 702 acpi_ut_get_node_name(node), node, op));
679 703
680 /* 704 /*