diff options
Diffstat (limited to 'drivers/acpi/executer')
-rw-r--r-- | drivers/acpi/executer/exfield.c | 24 | ||||
-rw-r--r-- | drivers/acpi/executer/exmutex.c | 194 | ||||
-rw-r--r-- | drivers/acpi/executer/exutils.c | 58 |
3 files changed, 160 insertions, 116 deletions
diff --git a/drivers/acpi/executer/exfield.c b/drivers/acpi/executer/exfield.c index 2d88a3d8d1a..e66b367c4fb 100644 --- a/drivers/acpi/executer/exfield.c +++ b/drivers/acpi/executer/exfield.c @@ -71,7 +71,6 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, union acpi_operand_object *buffer_desc; acpi_size length; void *buffer; - u8 locked; ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc); @@ -111,9 +110,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, /* Lock entire transaction if requested */ - locked = - acpi_ex_acquire_global_lock(obj_desc->common_field. - field_flags); + acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); /* * Perform the read. @@ -125,7 +122,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, buffer.pointer), ACPI_READ | (obj_desc->field. attribute << 16)); - acpi_ex_release_global_lock(locked); + acpi_ex_release_global_lock(); goto exit; } @@ -175,13 +172,12 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, /* Lock entire transaction if requested */ - locked = - acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); + acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); /* Read from the field */ status = acpi_ex_extract_from_field(obj_desc, buffer, (u32) length); - acpi_ex_release_global_lock(locked); + acpi_ex_release_global_lock(); exit: if (ACPI_FAILURE(status)) { @@ -217,7 +213,6 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, u32 required_length; void *buffer; void *new_buffer; - u8 locked; union acpi_operand_object *buffer_desc; ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc); @@ -278,9 +273,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, /* Lock entire transaction if requested */ - locked = - acpi_ex_acquire_global_lock(obj_desc->common_field. - field_flags); + acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); /* * Perform the write (returns status and perhaps data in the @@ -291,7 +284,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, (acpi_integer *) buffer, ACPI_WRITE | (obj_desc->field. attribute << 16)); - acpi_ex_release_global_lock(locked); + acpi_ex_release_global_lock(); *result_desc = buffer_desc; return_ACPI_STATUS(status); @@ -366,13 +359,12 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, /* Lock entire transaction if requested */ - locked = - acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); + acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); /* Write to the field */ status = acpi_ex_insert_into_field(obj_desc, buffer, length); - acpi_ex_release_global_lock(locked); + acpi_ex_release_global_lock(); /* Free temporary buffer if we used one */ diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c index 6748e3ef099..0bebe751aac 100644 --- a/drivers/acpi/executer/exmutex.c +++ b/drivers/acpi/executer/exmutex.c @@ -126,6 +126,66 @@ acpi_ex_link_mutex(union acpi_operand_object *obj_desc, /******************************************************************************* * + * FUNCTION: acpi_ex_acquire_mutex_object + * + * PARAMETERS: time_desc - Timeout in milliseconds + * obj_desc - Mutex object + * Thread - Current thread state + * + * RETURN: Status + * + * DESCRIPTION: Acquire an AML mutex, low-level interface + * + ******************************************************************************/ + +acpi_status +acpi_ex_acquire_mutex_object(u16 timeout, + union acpi_operand_object *obj_desc, + acpi_thread_id thread_id) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE_PTR(ex_acquire_mutex_object, obj_desc); + + /* Support for multiple acquires by the owning thread */ + + if (obj_desc->mutex.thread_id == thread_id) { + /* + * The mutex is already owned by this thread, just increment the + * acquisition depth + */ + obj_desc->mutex.acquisition_depth++; + return_ACPI_STATUS(AE_OK); + } + + /* Acquire the mutex, wait if necessary. Special case for Global Lock */ + + if (obj_desc == acpi_gbl_global_lock_mutex) { + status = acpi_ev_acquire_global_lock(timeout); + } else { + status = acpi_ex_system_wait_mutex(obj_desc->mutex.os_mutex, + timeout); + } + + if (ACPI_FAILURE(status)) { + + /* Includes failure from a timeout on time_desc */ + + return_ACPI_STATUS(status); + } + + /* Have the mutex: update mutex and save the sync_level */ + + obj_desc->mutex.thread_id = thread_id; + obj_desc->mutex.acquisition_depth = 1; + obj_desc->mutex.original_sync_level = 0; + obj_desc->mutex.owner_thread = NULL; /* Used only for AML Acquire() */ + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * * FUNCTION: acpi_ex_acquire_mutex * * PARAMETERS: time_desc - Timeout integer @@ -161,7 +221,7 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, } /* - * Current Sync must be less than or equal to the sync level of the + * Current Sync level must be less than or equal to the sync level of the * mutex. This mechanism provides some deadlock prevention */ if (walk_state->thread->current_sync_level > obj_desc->mutex.sync_level) { @@ -172,51 +232,70 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, return_ACPI_STATUS(AE_AML_MUTEX_ORDER); } - /* Support for multiple acquires by the owning thread */ + status = acpi_ex_acquire_mutex_object((u16) time_desc->integer.value, + obj_desc, + walk_state->thread->thread_id); + if (ACPI_SUCCESS(status) && obj_desc->mutex.acquisition_depth == 1) { + obj_desc->mutex.owner_thread = walk_state->thread; + obj_desc->mutex.original_sync_level = + walk_state->thread->current_sync_level; + walk_state->thread->current_sync_level = + obj_desc->mutex.sync_level; - if (obj_desc->mutex.owner_thread) { - if (obj_desc->mutex.owner_thread->thread_id == - walk_state->thread->thread_id) { - /* - * The mutex is already owned by this thread, just increment the - * acquisition depth - */ - obj_desc->mutex.acquisition_depth++; - return_ACPI_STATUS(AE_OK); - } + /* Link the mutex to the current thread for force-unlock at method exit */ + + acpi_ex_link_mutex(obj_desc, walk_state->thread); } - /* Acquire the mutex, wait if necessary. Special case for Global Lock */ + return_ACPI_STATUS(status); +} - if (obj_desc->mutex.os_mutex == acpi_gbl_global_lock_mutex) { - status = - acpi_ev_acquire_global_lock((u16) time_desc->integer.value); - } else { - status = acpi_ex_system_wait_mutex(obj_desc->mutex.os_mutex, - (u16) time_desc->integer. - value); - } +/******************************************************************************* + * + * FUNCTION: acpi_ex_release_mutex_object + * + * PARAMETERS: obj_desc - The object descriptor for this op + * + * RETURN: Status + * + * DESCRIPTION: Release a previously acquired Mutex, low level interface. + * + ******************************************************************************/ - if (ACPI_FAILURE(status)) { +acpi_status acpi_ex_release_mutex_object(union acpi_operand_object *obj_desc) +{ + acpi_status status = AE_OK; - /* Includes failure from a timeout on time_desc */ + ACPI_FUNCTION_TRACE(ex_release_mutex_object); - return_ACPI_STATUS(status); + /* Match multiple Acquires with multiple Releases */ + + obj_desc->mutex.acquisition_depth--; + if (obj_desc->mutex.acquisition_depth != 0) { + + /* Just decrement the depth and return */ + + return_ACPI_STATUS(AE_OK); } - /* Have the mutex: update mutex and walk info and save the sync_level */ + if (obj_desc->mutex.owner_thread) { - obj_desc->mutex.owner_thread = walk_state->thread; - obj_desc->mutex.acquisition_depth = 1; - obj_desc->mutex.original_sync_level = - walk_state->thread->current_sync_level; + /* Unlink the mutex from the owner's list */ + + acpi_ex_unlink_mutex(obj_desc); + obj_desc->mutex.owner_thread = NULL; + } - walk_state->thread->current_sync_level = obj_desc->mutex.sync_level; + /* Release the mutex, special case for Global Lock */ - /* Link the mutex to the current thread for force-unlock at method exit */ + if (obj_desc == acpi_gbl_global_lock_mutex) { + status = acpi_ev_release_global_lock(); + } else { + acpi_os_release_mutex(obj_desc->mutex.os_mutex); + } - acpi_ex_link_mutex(obj_desc, walk_state->thread); - return_ACPI_STATUS(AE_OK); + obj_desc->mutex.thread_id = 0; + return_ACPI_STATUS(status); } /******************************************************************************* @@ -253,22 +332,13 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED); } - /* Sanity check: we must have a valid thread ID */ - - if (!walk_state->thread) { - ACPI_ERROR((AE_INFO, - "Cannot release Mutex [%4.4s], null thread info", - acpi_ut_get_node_name(obj_desc->mutex.node))); - return_ACPI_STATUS(AE_AML_INTERNAL); - } - /* * The Mutex is owned, but this thread must be the owner. * Special case for Global Lock, any thread can release */ if ((obj_desc->mutex.owner_thread->thread_id != walk_state->thread->thread_id) - && (obj_desc->mutex.os_mutex != acpi_gbl_global_lock_mutex)) { + && (obj_desc != acpi_gbl_global_lock_mutex)) { ACPI_ERROR((AE_INFO, "Thread %lX cannot release Mutex [%4.4s] acquired by thread %lX", (unsigned long)walk_state->thread->thread_id, @@ -278,6 +348,15 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, return_ACPI_STATUS(AE_AML_NOT_OWNER); } + /* Sanity check: we must have a valid thread ID */ + + if (!walk_state->thread) { + ACPI_ERROR((AE_INFO, + "Cannot release Mutex [%4.4s], null thread info", + acpi_ut_get_node_name(obj_desc->mutex.node))); + return_ACPI_STATUS(AE_AML_INTERNAL); + } + /* * The sync level of the mutex must be less than or equal to the current * sync level @@ -289,34 +368,12 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, return_ACPI_STATUS(AE_AML_MUTEX_ORDER); } - /* Match multiple Acquires with multiple Releases */ - - obj_desc->mutex.acquisition_depth--; - if (obj_desc->mutex.acquisition_depth != 0) { - - /* Just decrement the depth and return */ - - return_ACPI_STATUS(AE_OK); - } - - /* Unlink the mutex from the owner's list */ + status = acpi_ex_release_mutex_object(obj_desc); - acpi_ex_unlink_mutex(obj_desc); - - /* Release the mutex, special case for Global Lock */ + /* Restore sync_level */ - if (obj_desc->mutex.os_mutex == acpi_gbl_global_lock_mutex) { - status = acpi_ev_release_global_lock(); - } else { - acpi_os_release_mutex(obj_desc->mutex.os_mutex); - } - - /* Update the mutex and restore sync_level */ - - obj_desc->mutex.owner_thread = NULL; walk_state->thread->current_sync_level = obj_desc->mutex.original_sync_level; - return_ACPI_STATUS(status); } @@ -357,7 +414,7 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread) /* Release the mutex, special case for Global Lock */ - if (obj_desc->mutex.os_mutex == acpi_gbl_global_lock_mutex) { + if (obj_desc == acpi_gbl_global_lock_mutex) { /* Ignore errors */ @@ -369,6 +426,7 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread) /* Mark mutex unowned */ obj_desc->mutex.owner_thread = NULL; + obj_desc->mutex.thread_id = 0; /* Update Thread sync_level (Last mutex is the important one) */ diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c index 6b0aeccbb69..c0837af0acb 100644 --- a/drivers/acpi/executer/exutils.c +++ b/drivers/acpi/executer/exutils.c @@ -240,72 +240,66 @@ void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc) * PARAMETERS: field_flags - Flags with Lock rule: * always_lock or never_lock * - * RETURN: TRUE/FALSE indicating whether the lock was actually acquired + * RETURN: None * - * DESCRIPTION: Obtain the global lock and keep track of this fact via two - * methods. A global variable keeps the state of the lock, and - * the state is returned to the caller. + * DESCRIPTION: Obtain the ACPI hardware Global Lock, only if the field + * flags specifiy that it is to be obtained before field access. * ******************************************************************************/ -u8 acpi_ex_acquire_global_lock(u32 field_flags) +void acpi_ex_acquire_global_lock(u32 field_flags) { - u8 locked = FALSE; acpi_status status; ACPI_FUNCTION_TRACE(ex_acquire_global_lock); - /* Only attempt lock if the always_lock bit is set */ + /* Only use the lock if the always_lock bit is set */ + + if (!(field_flags & AML_FIELD_LOCK_RULE_MASK)) { + return_VOID; + } - if (field_flags & AML_FIELD_LOCK_RULE_MASK) { + /* Attempt to get the global lock, wait forever */ - /* We should attempt to get the lock, wait forever */ + status = acpi_ex_acquire_mutex_object(ACPI_WAIT_FOREVER, + acpi_gbl_global_lock_mutex, + acpi_os_get_thread_id()); - status = acpi_ev_acquire_global_lock(ACPI_WAIT_FOREVER); - if (ACPI_SUCCESS(status)) { - locked = TRUE; - } else { - ACPI_EXCEPTION((AE_INFO, status, - "Could not acquire Global Lock")); - } + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Could not acquire Global Lock")); } - return_UINT8(locked); + return_VOID; } /******************************************************************************* * * FUNCTION: acpi_ex_release_global_lock * - * PARAMETERS: locked_by_me - Return value from corresponding call to - * acquire_global_lock. + * PARAMETERS: None * * RETURN: None * - * DESCRIPTION: Release the global lock if it is locked. + * DESCRIPTION: Release the ACPI hardware Global Lock * ******************************************************************************/ -void acpi_ex_release_global_lock(u8 locked_by_me) +void acpi_ex_release_global_lock(void) { acpi_status status; ACPI_FUNCTION_TRACE(ex_release_global_lock); - /* Only attempt unlock if the caller locked it */ - - if (locked_by_me) { + /* Release the global lock */ - /* OK, now release the lock */ - - status = acpi_ev_release_global_lock(); - if (ACPI_FAILURE(status)) { + status = acpi_ex_release_mutex_object(acpi_gbl_global_lock_mutex); + if (ACPI_FAILURE(status)) { - /* Report the error, but there isn't much else we can do */ + /* Report the error, but there isn't much else we can do */ - ACPI_EXCEPTION((AE_INFO, status, - "Could not release ACPI Global Lock")); - } + ACPI_EXCEPTION((AE_INFO, status, + "Could not release Global Lock")); } return_VOID; |