diff options
Diffstat (limited to 'drivers/acpi/acpica/dsmethod.c')
| -rw-r--r-- | drivers/acpi/acpica/dsmethod.c | 64 |
1 files changed, 48 insertions, 16 deletions
diff --git a/drivers/acpi/acpica/dsmethod.c b/drivers/acpi/acpica/dsmethod.c index d94dd8974b55..5d797751e205 100644 --- a/drivers/acpi/acpica/dsmethod.c +++ b/drivers/acpi/acpica/dsmethod.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
| 6 | 6 | ||
| 7 | /* | 7 | /* |
| 8 | * Copyright (C) 2000 - 2010, Intel Corp. | 8 | * Copyright (C) 2000 - 2011, Intel Corp. |
| 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 |
| @@ -43,7 +43,6 @@ | |||
| 43 | 43 | ||
| 44 | #include <acpi/acpi.h> | 44 | #include <acpi/acpi.h> |
| 45 | #include "accommon.h" | 45 | #include "accommon.h" |
| 46 | #include "amlcode.h" | ||
| 47 | #include "acdispat.h" | 46 | #include "acdispat.h" |
| 48 | #include "acinterp.h" | 47 | #include "acinterp.h" |
| 49 | #include "acnamesp.h" | 48 | #include "acnamesp.h" |
| @@ -201,7 +200,7 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, | |||
| 201 | /* | 200 | /* |
| 202 | * If this method is serialized, we need to acquire the method mutex. | 201 | * If this method is serialized, we need to acquire the method mutex. |
| 203 | */ | 202 | */ |
| 204 | if (obj_desc->method.method_flags & AML_METHOD_SERIALIZED) { | 203 | if (obj_desc->method.info_flags & ACPI_METHOD_SERIALIZED) { |
| 205 | /* | 204 | /* |
| 206 | * Create a mutex for the method if it is defined to be Serialized | 205 | * Create a mutex for the method if it is defined to be Serialized |
| 207 | * and a mutex has not already been created. We defer the mutex creation | 206 | * and a mutex has not already been created. We defer the mutex creation |
| @@ -413,8 +412,9 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, | |||
| 413 | 412 | ||
| 414 | /* Invoke an internal method if necessary */ | 413 | /* Invoke an internal method if necessary */ |
| 415 | 414 | ||
| 416 | if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) { | 415 | if (obj_desc->method.info_flags & ACPI_METHOD_INTERNAL_ONLY) { |
| 417 | status = obj_desc->method.extra.implementation(next_walk_state); | 416 | status = |
| 417 | obj_desc->method.dispatch.implementation(next_walk_state); | ||
| 418 | if (status == AE_OK) { | 418 | if (status == AE_OK) { |
| 419 | status = AE_CTRL_TERMINATE; | 419 | status = AE_CTRL_TERMINATE; |
| 420 | } | 420 | } |
| @@ -579,11 +579,14 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, | |||
| 579 | 579 | ||
| 580 | /* | 580 | /* |
| 581 | * Delete any namespace objects created anywhere within the | 581 | * Delete any namespace objects created anywhere within the |
| 582 | * namespace by the execution of this method. Unless this method | 582 | * namespace by the execution of this method. Unless: |
| 583 | * is a module-level executable code method, in which case we | 583 | * 1) This method is a module-level executable code method, in which |
| 584 | * want make the objects permanent. | 584 | * case we want make the objects permanent. |
| 585 | * 2) There are other threads executing the method, in which case we | ||
| 586 | * will wait until the last thread has completed. | ||
| 585 | */ | 587 | */ |
| 586 | if (!(method_desc->method.flags & AOPOBJ_MODULE_LEVEL)) { | 588 | if (!(method_desc->method.info_flags & ACPI_METHOD_MODULE_LEVEL) |
| 589 | && (method_desc->method.thread_count == 1)) { | ||
| 587 | 590 | ||
| 588 | /* Delete any direct children of (created by) this method */ | 591 | /* Delete any direct children of (created by) this method */ |
| 589 | 592 | ||
| @@ -593,12 +596,17 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, | |||
| 593 | /* | 596 | /* |
| 594 | * Delete any objects that were created by this method | 597 | * Delete any objects that were created by this method |
| 595 | * elsewhere in the namespace (if any were created). | 598 | * elsewhere in the namespace (if any were created). |
| 599 | * Use of the ACPI_METHOD_MODIFIED_NAMESPACE optimizes the | ||
| 600 | * deletion such that we don't have to perform an entire | ||
| 601 | * namespace walk for every control method execution. | ||
| 596 | */ | 602 | */ |
| 597 | if (method_desc->method. | 603 | if (method_desc->method. |
| 598 | flags & AOPOBJ_MODIFIED_NAMESPACE) { | 604 | info_flags & ACPI_METHOD_MODIFIED_NAMESPACE) { |
| 599 | acpi_ns_delete_namespace_by_owner(method_desc-> | 605 | acpi_ns_delete_namespace_by_owner(method_desc-> |
| 600 | method. | 606 | method. |
| 601 | owner_id); | 607 | owner_id); |
| 608 | method_desc->method.info_flags &= | ||
| 609 | ~ACPI_METHOD_MODIFIED_NAMESPACE; | ||
| 602 | } | 610 | } |
| 603 | } | 611 | } |
| 604 | } | 612 | } |
| @@ -629,19 +637,43 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, | |||
| 629 | * Serialized if it appears that the method is incorrectly written and | 637 | * Serialized if it appears that the method is incorrectly written and |
| 630 | * does not support multiple thread execution. The best example of this | 638 | * does not support multiple thread execution. The best example of this |
| 631 | * is if such a method creates namespace objects and blocks. A second | 639 | * is if such a method creates namespace objects and blocks. A second |
| 632 | * thread will fail with an AE_ALREADY_EXISTS exception | 640 | * thread will fail with an AE_ALREADY_EXISTS exception. |
| 633 | * | 641 | * |
| 634 | * This code is here because we must wait until the last thread exits | 642 | * This code is here because we must wait until the last thread exits |
| 635 | * before creating the synchronization semaphore. | 643 | * before marking the method as serialized. |
| 636 | */ | 644 | */ |
| 637 | if ((method_desc->method.method_flags & AML_METHOD_SERIALIZED) | 645 | if (method_desc->method. |
| 638 | && (!method_desc->method.mutex)) { | 646 | info_flags & ACPI_METHOD_SERIALIZED_PENDING) { |
| 639 | (void)acpi_ds_create_method_mutex(method_desc); | 647 | if (walk_state) { |
| 648 | ACPI_INFO((AE_INFO, | ||
| 649 | "Marking method %4.4s as Serialized because of AE_ALREADY_EXISTS error", | ||
| 650 | walk_state->method_node->name. | ||
| 651 | ascii)); | ||
| 652 | } | ||
| 653 | |||
| 654 | /* | ||
| 655 | * Method tried to create an object twice and was marked as | ||
| 656 | * "pending serialized". The probable cause is that the method | ||
| 657 | * cannot handle reentrancy. | ||
| 658 | * | ||
| 659 | * The method was created as not_serialized, but it tried to create | ||
| 660 | * a named object and then blocked, causing the second thread | ||
| 661 | * entrance to begin and then fail. Workaround this problem by | ||
| 662 | * marking the method permanently as Serialized when the last | ||
| 663 | * thread exits here. | ||
| 664 | */ | ||
| 665 | method_desc->method.info_flags &= | ||
| 666 | ~ACPI_METHOD_SERIALIZED_PENDING; | ||
| 667 | method_desc->method.info_flags |= | ||
| 668 | ACPI_METHOD_SERIALIZED; | ||
| 669 | method_desc->method.sync_level = 0; | ||
| 640 | } | 670 | } |
| 641 | 671 | ||
| 642 | /* No more threads, we can free the owner_id */ | 672 | /* No more threads, we can free the owner_id */ |
| 643 | 673 | ||
| 644 | if (!(method_desc->method.flags & AOPOBJ_MODULE_LEVEL)) { | 674 | if (! |
| 675 | (method_desc->method. | ||
| 676 | info_flags & ACPI_METHOD_MODULE_LEVEL)) { | ||
| 645 | acpi_ut_release_owner_id(&method_desc->method.owner_id); | 677 | acpi_ut_release_owner_id(&method_desc->method.owner_id); |
| 646 | } | 678 | } |
| 647 | } | 679 | } |
