Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 315c7288 authored by Bob Moore's avatar Bob Moore Committed by Len Brown
Browse files

ACPICA: Fix allowable release order for ASL mutex objects



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: default avatarBob Moore <robert.moore@intel.com>
Signed-off-by: default avatarLin Ming <ming.m.lin@intel.com>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent 10a3b461
Loading
Loading
Loading
Loading
+11 −4
Original line number Diff line number Diff line
@@ -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;
	}