diff options
Diffstat (limited to 'drivers/acpi/parser/psparse.c')
| -rw-r--r-- | drivers/acpi/parser/psparse.c | 55 |
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, |
