aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/parser/psparse.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/parser/psparse.c')
-rw-r--r--drivers/acpi/parser/psparse.c55
1 files changed, 35 insertions, 20 deletions
diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c
index 76d4d640d83c..a9f3229f4106 100644
--- a/drivers/acpi/parser/psparse.c
+++ b/drivers/acpi/parser/psparse.c
@@ -5,7 +5,7 @@
5 *****************************************************************************/ 5 *****************************************************************************/
6 6
7/* 7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore 8 * Copyright (C) 2000 - 2006, R. Byron Moore
9 * All rights reserved. 9 * All rights reserved.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
@@ -333,7 +333,6 @@ acpi_ps_next_parse_state(struct acpi_walk_state *walk_state,
333 333
334 switch (callback_status) { 334 switch (callback_status) {
335 case AE_CTRL_TERMINATE: 335 case AE_CTRL_TERMINATE:
336
337 /* 336 /*
338 * A control method was terminated via a RETURN statement. 337 * A control method was terminated via a RETURN statement.
339 * The walk of this method is complete. 338 * The walk of this method is complete.
@@ -346,13 +345,19 @@ acpi_ps_next_parse_state(struct acpi_walk_state *walk_state,
346 345
347 parser_state->aml = walk_state->aml_last_while; 346 parser_state->aml = walk_state->aml_last_while;
348 walk_state->control_state->common.value = FALSE; 347 walk_state->control_state->common.value = FALSE;
349 status = AE_CTRL_BREAK; 348 status = acpi_ds_result_stack_pop(walk_state);
349 if (ACPI_SUCCESS(status)) {
350 status = AE_CTRL_BREAK;
351 }
350 break; 352 break;
351 353
352 case AE_CTRL_CONTINUE: 354 case AE_CTRL_CONTINUE:
353 355
354 parser_state->aml = walk_state->aml_last_while; 356 parser_state->aml = walk_state->aml_last_while;
355 status = AE_CTRL_CONTINUE; 357 status = acpi_ds_result_stack_pop(walk_state);
358 if (ACPI_SUCCESS(status)) {
359 status = AE_CTRL_CONTINUE;
360 }
356 break; 361 break;
357 362
358 case AE_CTRL_PENDING: 363 case AE_CTRL_PENDING:
@@ -369,16 +374,18 @@ acpi_ps_next_parse_state(struct acpi_walk_state *walk_state,
369#endif 374#endif
370 375
371 case AE_CTRL_TRUE: 376 case AE_CTRL_TRUE:
372
373 /* 377 /*
374 * Predicate of an IF was true, and we are at the matching ELSE. 378 * Predicate of an IF was true, and we are at the matching ELSE.
375 * Just close out this package 379 * Just close out this package
376 */ 380 */
377 parser_state->aml = acpi_ps_get_next_package_end(parser_state); 381 parser_state->aml = acpi_ps_get_next_package_end(parser_state);
382 status = acpi_ds_result_stack_pop(walk_state);
383 if (ACPI_SUCCESS(status)) {
384 status = AE_CTRL_PENDING;
385 }
378 break; 386 break;
379 387
380 case AE_CTRL_FALSE: 388 case AE_CTRL_FALSE:
381
382 /* 389 /*
383 * Either an IF/WHILE Predicate was false or we encountered a BREAK 390 * Either an IF/WHILE Predicate was false or we encountered a BREAK
384 * opcode. In both cases, we do not execute the rest of the 391 * opcode. In both cases, we do not execute the rest of the
@@ -503,22 +510,23 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state)
503 } else if (status == AE_CTRL_TERMINATE) { 510 } else if (status == AE_CTRL_TERMINATE) {
504 status = AE_OK; 511 status = AE_OK;
505 } else if ((status != AE_OK) && (walk_state->method_desc)) { 512 } else if ((status != AE_OK) && (walk_state->method_desc)) {
506 ACPI_REPORT_METHOD_ERROR("Method execution failed", 513 /* Either the method parse or actual execution failed */
507 walk_state->method_node, NULL,
508 status);
509
510 /* Ensure proper cleanup */
511 514
512 walk_state->parse_flags |= ACPI_PARSE_EXECUTE; 515 ACPI_ERROR_METHOD("Method parse/execution failed",
516 walk_state->method_node, NULL,
517 status);
513 518
514 /* Check for possible multi-thread reentrancy problem */ 519 /* Check for possible multi-thread reentrancy problem */
515 520
516 if ((status == AE_ALREADY_EXISTS) && 521 if ((status == AE_ALREADY_EXISTS) &&
517 (!walk_state->method_desc->method.semaphore)) { 522 (!walk_state->method_desc->method.semaphore)) {
518 /* 523 /*
519 * This method is marked not_serialized, but it tried to create 524 * Method tried to create an object twice. The probable cause is
525 * that the method cannot handle reentrancy.
526 *
527 * The method is marked not_serialized, but it tried to create
520 * a named object, causing the second thread entrance to fail. 528 * a named object, causing the second thread entrance to fail.
521 * We will workaround this by marking the method permanently 529 * Workaround this problem by marking the method permanently
522 * as Serialized. 530 * as Serialized.
523 */ 531 */
524 walk_state->method_desc->method.method_flags |= 532 walk_state->method_desc->method.method_flags |=
@@ -536,15 +544,23 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state)
536 acpi_ds_scope_stack_clear(walk_state); 544 acpi_ds_scope_stack_clear(walk_state);
537 545
538 /* 546 /*
539 * If we just returned from the execution of a control method, 547 * If we just returned from the execution of a control method or if we
540 * there's lots of cleanup to do 548 * encountered an error during the method parse phase, there's lots of
549 * cleanup to do
541 */ 550 */
542 if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) == 551 if (((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) ==
543 ACPI_PARSE_EXECUTE) { 552 ACPI_PARSE_EXECUTE) || (ACPI_FAILURE(status))) {
544 if (walk_state->method_desc) { 553 if (walk_state->method_desc) {
545 /* Decrement the thread count on the method parse tree */ 554 /* Decrement the thread count on the method parse tree */
546 555
547 walk_state->method_desc->method.thread_count--; 556 if (walk_state->method_desc->method.
557 thread_count) {
558 walk_state->method_desc->method.
559 thread_count--;
560 } else {
561 ACPI_ERROR((AE_INFO,
562 "Invalid zero thread count in method"));
563 }
548 } 564 }
549 565
550 acpi_ds_terminate_control_method(walk_state); 566 acpi_ds_terminate_control_method(walk_state);
@@ -553,7 +569,6 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state)
553 /* Delete this walk state and all linked control states */ 569 /* Delete this walk state and all linked control states */
554 570
555 acpi_ps_cleanup_scope(&walk_state->parser_state); 571 acpi_ps_cleanup_scope(&walk_state->parser_state);
556
557 previous_walk_state = walk_state; 572 previous_walk_state = walk_state;
558 573
559 ACPI_DEBUG_PRINT((ACPI_DB_PARSE, 574 ACPI_DEBUG_PRINT((ACPI_DB_PARSE,