ACPICA: Fix allowable release order for ASL mutex objects
authorBob Moore <robert.moore@intel.com>
Thu, 21 May 2009 02:04:33 +0000 (10:04 +0800)
committerLen Brown <len.brown@intel.com>
Wed, 27 May 2009 04:32:24 +0000 (00:32 -0400)
The ACPI 4.0 specification has been changed to make the SyncLevel
for mutex objects more useful. When releasing a mutex, the
synclevel of the mutex must now be the same as the current sync
level. This makes more sense. This change updates the code to
match the spec.

Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
drivers/acpi/acpica/exmutex.c

index 77a592aa53c0621e0bc9b3a34b3152d209d17ceb..2f0114202b05dc8a86e77b31075d3e930e96718f 100644 (file)
@@ -402,10 +402,14 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
        }
 
        /*
-        * The sync level of the mutex must be less than or equal to the current
-        * sync level
+        * The sync level of the mutex must be equal to the current sync level. In
+        * other words, the current level means that at least one mutex at that
+        * level is currently being held. Attempting to release a mutex of a
+        * different level can only mean that the mutex ordering rule is being
+        * violated. This behavior is clarified in ACPI 4.0 specification.
         */
-       if (obj_desc->mutex.sync_level > walk_state->thread->current_sync_level) {
+       if (obj_desc->mutex.sync_level !=
+           walk_state->thread->current_sync_level) {
                ACPI_ERROR((AE_INFO,
                            "Cannot release Mutex [%4.4s], SyncLevel mismatch: mutex %d current %d",
                            acpi_ut_get_node_name(obj_desc->mutex.node),
@@ -423,10 +427,13 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
            walk_state->thread->acquired_mutex_list->mutex.original_sync_level;
 
        status = acpi_ex_release_mutex_object(obj_desc);
+       if (ACPI_FAILURE(status)) {
+               return_ACPI_STATUS(status);
+       }
 
        if (obj_desc->mutex.acquisition_depth == 0) {
 
-               /* Restore the original sync_level */
+               /* Restore the previous sync_level */
 
                walk_state->thread->current_sync_level = previous_sync_level;
        }