aboutsummaryrefslogtreecommitdiff
path: root/drivers/acpi/utilities/utmisc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/utilities/utmisc.c')
-rw-r--r--drivers/acpi/utilities/utmisc.c799
1 files changed, 120 insertions, 679 deletions
diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c
index f6de4ed3d52..1d350b302a3 100644
--- a/drivers/acpi/utilities/utmisc.c
+++ b/drivers/acpi/utilities/utmisc.c
@@ -49,15 +49,121 @@
#define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME ("utmisc")
-/* Local prototypes */
-static acpi_status
-acpi_ut_create_mutex (
- acpi_mutex_handle mutex_id);
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_allocate_owner_id
+ *
+ * PARAMETERS: owner_id - Where the new owner ID is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Allocate a table or method owner ID. The owner ID is used to
+ * track objects created by the table or method, to be deleted
+ * when the method exits or the table is unloaded.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ut_allocate_owner_id (
+ acpi_owner_id *owner_id)
+{
+ acpi_native_uint i;
+ acpi_status status;
+
+
+ ACPI_FUNCTION_TRACE ("ut_allocate_owner_id");
-static acpi_status
-acpi_ut_delete_mutex (
- acpi_mutex_handle mutex_id);
+
+ /* Mutex for the global ID mask */
+
+ status = acpi_ut_acquire_mutex (ACPI_MTX_CACHES);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
+ /* Find a free owner ID */
+
+ for (i = 0; i < 32; i++) {
+ if (!(acpi_gbl_owner_id_mask & (1 << i))) {
+ acpi_gbl_owner_id_mask |= (1 << i);
+ *owner_id = (acpi_owner_id) (i + 1);
+ goto exit;
+ }
+ }
+
+ /*
+ * If we are here, all owner_ids have been allocated. This probably should
+ * not happen since the IDs are reused after deallocation. The IDs are
+ * allocated upon table load (one per table) and method execution, and
+ * they are released when a table is unloaded or a method completes
+ * execution.
+ */
+ *owner_id = 0;
+ status = AE_OWNER_ID_LIMIT;
+ ACPI_REPORT_ERROR ((
+ "Could not allocate new owner_id (32 max), AE_OWNER_ID_LIMIT\n"));
+
+exit:
+ (void) acpi_ut_release_mutex (ACPI_MTX_CACHES);
+ return_ACPI_STATUS (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_release_owner_id
+ *
+ * PARAMETERS: owner_id_ptr - Pointer to a previously allocated owner_iD
+ *
+ * RETURN: None. No error is returned because we are either exiting a
+ * control method or unloading a table. Either way, we would
+ * ignore any error anyway.
+ *
+ * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 32
+ *
+ ******************************************************************************/
+
+void
+acpi_ut_release_owner_id (
+ acpi_owner_id *owner_id_ptr)
+{
+ acpi_owner_id owner_id = *owner_id_ptr;
+ acpi_status status;
+
+
+ ACPI_FUNCTION_TRACE ("ut_release_owner_id");
+
+
+ /* Always clear the input owner_id (zero is an invalid ID) */
+
+ *owner_id_ptr = 0;
+
+ /* Zero is not a valid owner_iD */
+
+ if ((owner_id == 0) || (owner_id > 32)) {
+ ACPI_REPORT_ERROR (("Invalid owner_id: %2.2X\n", owner_id));
+ return_VOID;
+ }
+
+ /* Mutex for the global ID mask */
+
+ status = acpi_ut_acquire_mutex (ACPI_MTX_CACHES);
+ if (ACPI_FAILURE (status)) {
+ return_VOID;
+ }
+
+ owner_id--; /* Normalize to zero */
+
+ /* Free the owner ID only if it is valid */
+
+ if (acpi_gbl_owner_id_mask & (1 << owner_id)) {
+ acpi_gbl_owner_id_mask ^= (1 << owner_id);
+ }
+
+ (void) acpi_ut_release_mutex (ACPI_MTX_CACHES);
+ return_VOID;
+}
/*******************************************************************************
@@ -66,7 +172,7 @@ acpi_ut_delete_mutex (
*
* PARAMETERS: src_string - The source string to convert
*
- * RETURN: Converted src_string (same as input pointer)
+ * RETURN: None
*
* DESCRIPTION: Convert string to uppercase
*
@@ -74,7 +180,7 @@ acpi_ut_delete_mutex (
*
******************************************************************************/
-char *
+void
acpi_ut_strupr (
char *src_string)
{
@@ -84,13 +190,17 @@ acpi_ut_strupr (
ACPI_FUNCTION_ENTRY ();
+ if (!src_string) {
+ return;
+ }
+
/* Walk entire string, uppercasing the letters */
for (string = src_string; *string; string++) {
*string = (char) ACPI_TOUPPER (*string);
}
- return (src_string);
+ return;
}
@@ -543,320 +653,6 @@ error_exit:
/*******************************************************************************
*
- * FUNCTION: acpi_ut_mutex_initialize
- *
- * PARAMETERS: None.
- *
- * RETURN: Status
- *
- * DESCRIPTION: Create the system mutex objects.
- *
- ******************************************************************************/
-
-acpi_status
-acpi_ut_mutex_initialize (
- void)
-{
- u32 i;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ut_mutex_initialize");
-
-
- /*
- * Create each of the predefined mutex objects
- */
- for (i = 0; i < NUM_MUTEX; i++) {
- status = acpi_ut_create_mutex (i);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
- }
- }
-
- status = acpi_os_create_lock (&acpi_gbl_gpe_lock);
- return_ACPI_STATUS (status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_mutex_terminate
- *
- * PARAMETERS: None.
- *
- * RETURN: None.
- *
- * DESCRIPTION: Delete all of the system mutex objects.
- *
- ******************************************************************************/
-
-void
-acpi_ut_mutex_terminate (
- void)
-{
- u32 i;
-
-
- ACPI_FUNCTION_TRACE ("ut_mutex_terminate");
-
-
- /*
- * Delete each predefined mutex object
- */
- for (i = 0; i < NUM_MUTEX; i++) {
- (void) acpi_ut_delete_mutex (i);
- }
-
- acpi_os_delete_lock (acpi_gbl_gpe_lock);
- return_VOID;
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_create_mutex
- *
- * PARAMETERS: mutex_iD - ID of the mutex to be created
- *
- * RETURN: Status
- *
- * DESCRIPTION: Create a mutex object.
- *
- ******************************************************************************/
-
-static acpi_status
-acpi_ut_create_mutex (
- acpi_mutex_handle mutex_id)
-{
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE_U32 ("ut_create_mutex", mutex_id);
-
-
- if (mutex_id > MAX_MUTEX) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
- }
-
- if (!acpi_gbl_mutex_info[mutex_id].mutex) {
- status = acpi_os_create_semaphore (1, 1,
- &acpi_gbl_mutex_info[mutex_id].mutex);
- acpi_gbl_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED;
- acpi_gbl_mutex_info[mutex_id].use_count = 0;
- }
-
- return_ACPI_STATUS (status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_delete_mutex
- *
- * PARAMETERS: mutex_iD - ID of the mutex to be deleted
- *
- * RETURN: Status
- *
- * DESCRIPTION: Delete a mutex object.
- *
- ******************************************************************************/
-
-static acpi_status
-acpi_ut_delete_mutex (
- acpi_mutex_handle mutex_id)
-{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE_U32 ("ut_delete_mutex", mutex_id);
-
-
- if (mutex_id > MAX_MUTEX) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
- }
-
- status = acpi_os_delete_semaphore (acpi_gbl_mutex_info[mutex_id].mutex);
-
- acpi_gbl_mutex_info[mutex_id].mutex = NULL;
- acpi_gbl_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED;
-
- return_ACPI_STATUS (status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_acquire_mutex
- *
- * PARAMETERS: mutex_iD - ID of the mutex to be acquired
- *
- * RETURN: Status
- *
- * DESCRIPTION: Acquire a mutex object.
- *
- ******************************************************************************/
-
-acpi_status
-acpi_ut_acquire_mutex (
- acpi_mutex_handle mutex_id)
-{
- acpi_status status;
- u32 this_thread_id;
-
-
- ACPI_FUNCTION_NAME ("ut_acquire_mutex");
-
-
- if (mutex_id > MAX_MUTEX) {
- return (AE_BAD_PARAMETER);
- }
-
- this_thread_id = acpi_os_get_thread_id ();
-
-#ifdef ACPI_MUTEX_DEBUG
- {
- u32 i;
- /*
- * Mutex debug code, for internal debugging only.
- *
- * Deadlock prevention. Check if this thread owns any mutexes of value
- * greater than or equal to this one. If so, the thread has violated
- * the mutex ordering rule. This indicates a coding error somewhere in
- * the ACPI subsystem code.
- */
- for (i = mutex_id; i < MAX_MUTEX; i++) {
- if (acpi_gbl_mutex_info[i].owner_id == this_thread_id) {
- if (i == mutex_id) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Mutex [%s] already acquired by this thread [%X]\n",
- acpi_ut_get_mutex_name (mutex_id), this_thread_id));
-
- return (AE_ALREADY_ACQUIRED);
- }
-
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Invalid acquire order: Thread %X owns [%s], wants [%s]\n",
- this_thread_id, acpi_ut_get_mutex_name (i),
- acpi_ut_get_mutex_name (mutex_id)));
-
- return (AE_ACQUIRE_DEADLOCK);
- }
- }
- }
-#endif
-
- ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX,
- "Thread %X attempting to acquire Mutex [%s]\n",
- this_thread_id, acpi_ut_get_mutex_name (mutex_id)));
-
- status = acpi_os_wait_semaphore (acpi_gbl_mutex_info[mutex_id].mutex,
- 1, ACPI_WAIT_FOREVER);
- if (ACPI_SUCCESS (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %X acquired Mutex [%s]\n",
- this_thread_id, acpi_ut_get_mutex_name (mutex_id)));
-
- acpi_gbl_mutex_info[mutex_id].use_count++;
- acpi_gbl_mutex_info[mutex_id].owner_id = this_thread_id;
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Thread %X could not acquire Mutex [%s] %s\n",
- this_thread_id, acpi_ut_get_mutex_name (mutex_id),
- acpi_format_exception (status)));
- }
-
- return (status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_release_mutex
- *
- * PARAMETERS: mutex_iD - ID of the mutex to be released
- *
- * RETURN: Status
- *
- * DESCRIPTION: Release a mutex object.
- *
- ******************************************************************************/
-
-acpi_status
-acpi_ut_release_mutex (
- acpi_mutex_handle mutex_id)
-{
- acpi_status status;
- u32 i;
- u32 this_thread_id;
-
-
- ACPI_FUNCTION_NAME ("ut_release_mutex");
-
-
- this_thread_id = acpi_os_get_thread_id ();
- ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX,
- "Thread %X releasing Mutex [%s]\n", this_thread_id,
- acpi_ut_get_mutex_name (mutex_id)));
-
- if (mutex_id > MAX_MUTEX) {
- return (AE_BAD_PARAMETER);
- }
-
- /*
- * Mutex must be acquired in order to release it!
- */
- if (acpi_gbl_mutex_info[mutex_id].owner_id == ACPI_MUTEX_NOT_ACQUIRED) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Mutex [%s] is not acquired, cannot release\n",
- acpi_ut_get_mutex_name (mutex_id)));
-
- return (AE_NOT_ACQUIRED);
- }
-
- /*
- * Deadlock prevention. Check if this thread owns any mutexes of value
- * greater than this one. If so, the thread has violated the mutex
- * ordering rule. This indicates a coding error somewhere in
- * the ACPI subsystem code.
- */
- for (i = mutex_id; i < MAX_MUTEX; i++) {
- if (acpi_gbl_mutex_info[i].owner_id == this_thread_id) {
- if (i == mutex_id) {
- continue;
- }
-
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Invalid release order: owns [%s], releasing [%s]\n",
- acpi_ut_get_mutex_name (i), acpi_ut_get_mutex_name (mutex_id)));
-
- return (AE_RELEASE_DEADLOCK);
- }
- }
-
- /* Mark unlocked FIRST */
-
- acpi_gbl_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED;
-
- status = acpi_os_signal_semaphore (acpi_gbl_mutex_info[mutex_id].mutex, 1);
-
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Thread %X could not release Mutex [%s] %s\n",
- this_thread_id, acpi_ut_get_mutex_name (mutex_id),
- acpi_format_exception (status)));
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %X released Mutex [%s]\n",
- this_thread_id, acpi_ut_get_mutex_name (mutex_id)));
- }
-
- return (status);
-}
-
-
-/*******************************************************************************
- *
* FUNCTION: acpi_ut_create_update_state_and_push
*
* PARAMETERS: Object - Object to be added to the new state
@@ -899,361 +695,6 @@ acpi_ut_create_update_state_and_push (
/*******************************************************************************
*
- * FUNCTION: acpi_ut_create_pkg_state_and_push
- *
- * PARAMETERS: Object - Object to be added to the new state
- * Action - Increment/Decrement
- * state_list - List the state will be added to
- *
- * RETURN: Status
- *
- * DESCRIPTION: Create a new state and push it
- *
- ******************************************************************************/
-
-#ifdef ACPI_FUTURE_USAGE
-acpi_status
-acpi_ut_create_pkg_state_and_push (
- void *internal_object,
- void *external_object,
- u16 index,
- union acpi_generic_state **state_list)
-{
- union acpi_generic_state *state;
-
-
- ACPI_FUNCTION_ENTRY ();
-
-
- state = acpi_ut_create_pkg_state (internal_object, external_object, index);
- if (!state) {
- return (AE_NO_MEMORY);
- }
-
- acpi_ut_push_generic_state (state_list, state);
- return (AE_OK);
-}
-#endif /* ACPI_FUTURE_USAGE */
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_push_generic_state
- *
- * PARAMETERS: list_head - Head of the state stack
- * State - State object to push
- *
- * RETURN: None
- *
- * DESCRIPTION: Push a state object onto a state stack
- *
- ******************************************************************************/
-
-void
-acpi_ut_push_generic_state (
- union acpi_generic_state **list_head,
- union acpi_generic_state *state)
-{
- ACPI_FUNCTION_TRACE ("ut_push_generic_state");
-
-
- /* Push the state object onto the front of the list (stack) */
-
- state->common.next = *list_head;
- *list_head = state;
-
- return_VOID;
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_pop_generic_state
- *
- * PARAMETERS: list_head - Head of the state stack
- *
- * RETURN: The popped state object
- *
- * DESCRIPTION: Pop a state object from a state stack
- *
- ******************************************************************************/
-
-union acpi_generic_state *
-acpi_ut_pop_generic_state (
- union acpi_generic_state **list_head)
-{
- union acpi_generic_state *state;
-
-
- ACPI_FUNCTION_TRACE ("ut_pop_generic_state");
-
-
- /* Remove the state object at the head of the list (stack) */
-
- state = *list_head;
- if (state) {
- /* Update the list head */
-
- *list_head = state->common.next;
- }
-
- return_PTR (state);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_create_generic_state
- *
- * PARAMETERS: None
- *
- * RETURN: The new state object. NULL on failure.
- *
- * DESCRIPTION: Create a generic state object. Attempt to obtain one from
- * the global state cache; If none available, create a new one.
- *
- ******************************************************************************/
-
-union acpi_generic_state *
-acpi_ut_create_generic_state (
- void)
-{
- union acpi_generic_state *state;
-
-
- ACPI_FUNCTION_ENTRY ();
-
-
- state = acpi_ut_acquire_from_cache (ACPI_MEM_LIST_STATE);
-
- /* Initialize */
-
- if (state) {
- state->common.data_type = ACPI_DESC_TYPE_STATE;
- }
-
- return (state);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_create_thread_state
- *
- * PARAMETERS: None
- *
- * RETURN: New Thread State. NULL on failure
- *
- * DESCRIPTION: Create a "Thread State" - a flavor of the generic state used
- * to track per-thread info during method execution
- *
- ******************************************************************************/
-
-struct acpi_thread_state *
-acpi_ut_create_thread_state (
- void)
-{
- union acpi_generic_state *state;
-
-
- ACPI_FUNCTION_TRACE ("ut_create_thread_state");
-
-
- /* Create the generic state object */
-
- state = acpi_ut_create_generic_state ();
- if (!state) {
- return_PTR (NULL);
- }
-
- /* Init fields specific to the update struct */
-
- state->common.data_type = ACPI_DESC_TYPE_STATE_THREAD;
- state->thread.thread_id = acpi_os_get_thread_id ();
-
- return_PTR ((struct acpi_thread_state *) state);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_create_update_state
- *
- * PARAMETERS: Object - Initial Object to be installed in the state
- * Action - Update action to be performed
- *
- * RETURN: New state object, null on failure
- *
- * DESCRIPTION: Create an "Update State" - a flavor of the generic state used
- * to update reference counts and delete complex objects such
- * as packages.
- *
- ******************************************************************************/
-
-union acpi_generic_state *
-acpi_ut_create_update_state (
- union acpi_operand_object *object,
- u16 action)
-{
- union acpi_generic_state *state;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ut_create_update_state", object);
-
-
- /* Create the generic state object */
-
- state = acpi_ut_create_generic_state ();
- if (!state) {
- return_PTR (NULL);
- }
-
- /* Init fields specific to the update struct */
-
- state->common.data_type = ACPI_DESC_TYPE_STATE_UPDATE;
- state->update.object = object;
- state->update.value = action;
-
- return_PTR (state);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_create_pkg_state
- *
- * PARAMETERS: Object - Initial Object to be installed in the state
- * Action - Update action to be performed
- *
- * RETURN: New state object, null on failure
- *
- * DESCRIPTION: Create a "Package State"
- *
- ******************************************************************************/
-
-union acpi_generic_state *
-acpi_ut_create_pkg_state (
- void *internal_object,
- void *external_object,
- u16 index)
-{
- union acpi_generic_state *state;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ut_create_pkg_state", internal_object);
-
-
- /* Create the generic state object */
-
- state = acpi_ut_create_generic_state ();
- if (!state) {
- return_PTR (NULL);
- }
-
- /* Init fields specific to the update struct */
-
- state->common.data_type = ACPI_DESC_TYPE_STATE_PACKAGE;
- state->pkg.source_object = (union acpi_operand_object *) internal_object;
- state->pkg.dest_object = external_object;
- state->pkg.index = index;
- state->pkg.num_packages = 1;
-
- return_PTR (state);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_create_control_state
- *
- * PARAMETERS: None
- *
- * RETURN: New state object, null on failure
- *
- * DESCRIPTION: Create a "Control State" - a flavor of the generic state used
- * to support nested IF/WHILE constructs in the AML.
- *
- ******************************************************************************/
-
-union acpi_generic_state *
-acpi_ut_create_control_state (
- void)
-{
- union acpi_generic_state *state;
-
-
- ACPI_FUNCTION_TRACE ("ut_create_control_state");
-
-
- /* Create the generic state object */
-
- state = acpi_ut_create_generic_state ();
- if (!state) {
- return_PTR (NULL);
- }
-
- /* Init fields specific to the control struct */
-
- state->common.data_type = ACPI_DESC_TYPE_STATE_CONTROL;
- state->common.state = ACPI_CONTROL_CONDITIONAL_EXECUTING;
-
- return_PTR (state);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_delete_generic_state
- *
- * PARAMETERS: State - The state object to be deleted
- *
- * RETURN: None
- *
- * DESCRIPTION: Put a state object back into the global state cache. The object
- * is not actually freed at this time.
- *
- ******************************************************************************/
-
-void
-acpi_ut_delete_generic_state (
- union acpi_generic_state *state)
-{
- ACPI_FUNCTION_TRACE ("ut_delete_generic_state");
-
-
- acpi_ut_release_to_cache (ACPI_MEM_LIST_STATE, state);
- return_VOID;
-}
-
-
-#ifdef ACPI_ENABLE_OBJECT_CACHE
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_delete_generic_state_cache
- *
- * PARAMETERS: None
- *
- * RETURN: None
- *
- * DESCRIPTION: Purge the global state object cache. Used during subsystem
- * termination.
- *
- ******************************************************************************/
-
-void
-acpi_ut_delete_generic_state_cache (
- void)
-{
- ACPI_FUNCTION_TRACE ("ut_delete_generic_state_cache");
-
-
- acpi_ut_delete_generic_cache (ACPI_MEM_LIST_STATE);
- return_VOID;
-}
-#endif
-
-
-/*******************************************************************************
- *
* FUNCTION: acpi_ut_walk_package_tree
*
* PARAMETERS: source_object - The package to walk