195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
295b482a8SLen Brown /*******************************************************************************
395b482a8SLen Brown *
495b482a8SLen Brown * Module Name: utmutex - local mutex support
595b482a8SLen Brown *
695b482a8SLen Brown ******************************************************************************/
795b482a8SLen Brown
895b482a8SLen Brown #include <acpi/acpi.h>
9e2f7a777SLen Brown #include "accommon.h"
1095b482a8SLen Brown
1195b482a8SLen Brown #define _COMPONENT ACPI_UTILITIES
1295b482a8SLen Brown ACPI_MODULE_NAME("utmutex")
1395b482a8SLen Brown
1495b482a8SLen Brown /* Local prototypes */
1595b482a8SLen Brown static acpi_status acpi_ut_create_mutex(acpi_mutex_handle mutex_id);
1695b482a8SLen Brown
172147d3f0SBob Moore static void acpi_ut_delete_mutex(acpi_mutex_handle mutex_id);
1895b482a8SLen Brown
1995b482a8SLen Brown /*******************************************************************************
2095b482a8SLen Brown *
2195b482a8SLen Brown * FUNCTION: acpi_ut_mutex_initialize
2295b482a8SLen Brown *
2395b482a8SLen Brown * PARAMETERS: None.
2495b482a8SLen Brown *
2595b482a8SLen Brown * RETURN: Status
2695b482a8SLen Brown *
278a335a23SBob Moore * DESCRIPTION: Create the system mutex objects. This includes mutexes,
288a335a23SBob Moore * spin locks, and reader/writer locks.
2995b482a8SLen Brown *
3095b482a8SLen Brown ******************************************************************************/
3195b482a8SLen Brown
acpi_ut_mutex_initialize(void)3295b482a8SLen Brown acpi_status acpi_ut_mutex_initialize(void)
3395b482a8SLen Brown {
3495b482a8SLen Brown u32 i;
3595b482a8SLen Brown acpi_status status;
3695b482a8SLen Brown
3795b482a8SLen Brown ACPI_FUNCTION_TRACE(ut_mutex_initialize);
3895b482a8SLen Brown
398a335a23SBob Moore /* Create each of the predefined mutex objects */
408a335a23SBob Moore
4195b482a8SLen Brown for (i = 0; i < ACPI_NUM_MUTEX; i++) {
4295b482a8SLen Brown status = acpi_ut_create_mutex(i);
4395b482a8SLen Brown if (ACPI_FAILURE(status)) {
4495b482a8SLen Brown return_ACPI_STATUS(status);
4595b482a8SLen Brown }
4695b482a8SLen Brown }
4795b482a8SLen Brown
4858892c96SBob Moore /* Create the spinlocks for use at interrupt level or for speed */
4995b482a8SLen Brown
503854c8e3SLin Ming status = acpi_os_create_lock (&acpi_gbl_gpe_lock);
513854c8e3SLin Ming if (ACPI_FAILURE (status)) {
523854c8e3SLin Ming return_ACPI_STATUS (status);
533854c8e3SLin Ming }
543854c8e3SLin Ming
55*c57c0ad4SSteven Rostedt status = acpi_os_create_raw_lock(&acpi_gbl_hardware_lock);
563854c8e3SLin Ming if (ACPI_FAILURE (status)) {
573854c8e3SLin Ming return_ACPI_STATUS (status);
583854c8e3SLin Ming }
593854c8e3SLin Ming
6058892c96SBob Moore status = acpi_os_create_lock(&acpi_gbl_reference_count_lock);
6158892c96SBob Moore if (ACPI_FAILURE(status)) {
6258892c96SBob Moore return_ACPI_STATUS(status);
6358892c96SBob Moore }
6458892c96SBob Moore
65b0ed7a91SLin Ming /* Mutex for _OSI support */
6658892c96SBob Moore
67b0ed7a91SLin Ming status = acpi_os_create_mutex(&acpi_gbl_osi_mutex);
68b0ed7a91SLin Ming if (ACPI_FAILURE(status)) {
69b0ed7a91SLin Ming return_ACPI_STATUS(status);
70b0ed7a91SLin Ming }
71b0ed7a91SLin Ming
728a335a23SBob Moore /* Create the reader/writer lock for namespace access */
738a335a23SBob Moore
748a335a23SBob Moore status = acpi_ut_create_rw_lock(&acpi_gbl_namespace_rw_lock);
75cd64bbf8SBob Moore if (ACPI_FAILURE(status)) {
76cd64bbf8SBob Moore return_ACPI_STATUS(status);
77cd64bbf8SBob Moore }
78cd64bbf8SBob Moore
7995b482a8SLen Brown return_ACPI_STATUS(status);
8095b482a8SLen Brown }
8195b482a8SLen Brown
8295b482a8SLen Brown /*******************************************************************************
8395b482a8SLen Brown *
8495b482a8SLen Brown * FUNCTION: acpi_ut_mutex_terminate
8595b482a8SLen Brown *
8695b482a8SLen Brown * PARAMETERS: None.
8795b482a8SLen Brown *
8895b482a8SLen Brown * RETURN: None.
8995b482a8SLen Brown *
908a335a23SBob Moore * DESCRIPTION: Delete all of the system mutex objects. This includes mutexes,
918a335a23SBob Moore * spin locks, and reader/writer locks.
9295b482a8SLen Brown *
9395b482a8SLen Brown ******************************************************************************/
9495b482a8SLen Brown
acpi_ut_mutex_terminate(void)9595b482a8SLen Brown void acpi_ut_mutex_terminate(void)
9695b482a8SLen Brown {
9795b482a8SLen Brown u32 i;
9895b482a8SLen Brown
9995b482a8SLen Brown ACPI_FUNCTION_TRACE(ut_mutex_terminate);
10095b482a8SLen Brown
1018a335a23SBob Moore /* Delete each predefined mutex object */
1028a335a23SBob Moore
10395b482a8SLen Brown for (i = 0; i < ACPI_NUM_MUTEX; i++) {
1042147d3f0SBob Moore acpi_ut_delete_mutex(i);
10595b482a8SLen Brown }
10695b482a8SLen Brown
107b0ed7a91SLin Ming acpi_os_delete_mutex(acpi_gbl_osi_mutex);
108b0ed7a91SLin Ming
10995b482a8SLen Brown /* Delete the spinlocks */
11095b482a8SLen Brown
11195b482a8SLen Brown acpi_os_delete_lock(acpi_gbl_gpe_lock);
112*c57c0ad4SSteven Rostedt acpi_os_delete_raw_lock(acpi_gbl_hardware_lock);
11358892c96SBob Moore acpi_os_delete_lock(acpi_gbl_reference_count_lock);
1148a335a23SBob Moore
1158a335a23SBob Moore /* Delete the reader/writer lock */
1168a335a23SBob Moore
1178a335a23SBob Moore acpi_ut_delete_rw_lock(&acpi_gbl_namespace_rw_lock);
11895b482a8SLen Brown return_VOID;
11995b482a8SLen Brown }
12095b482a8SLen Brown
12195b482a8SLen Brown /*******************************************************************************
12295b482a8SLen Brown *
12395b482a8SLen Brown * FUNCTION: acpi_ut_create_mutex
12495b482a8SLen Brown *
125ba494beeSBob Moore * PARAMETERS: mutex_ID - ID of the mutex to be created
12695b482a8SLen Brown *
12795b482a8SLen Brown * RETURN: Status
12895b482a8SLen Brown *
12995b482a8SLen Brown * DESCRIPTION: Create a mutex object.
13095b482a8SLen Brown *
13195b482a8SLen Brown ******************************************************************************/
13295b482a8SLen Brown
acpi_ut_create_mutex(acpi_mutex_handle mutex_id)13395b482a8SLen Brown static acpi_status acpi_ut_create_mutex(acpi_mutex_handle mutex_id)
13495b482a8SLen Brown {
13595b482a8SLen Brown acpi_status status = AE_OK;
13695b482a8SLen Brown
13795b482a8SLen Brown ACPI_FUNCTION_TRACE_U32(ut_create_mutex, mutex_id);
13895b482a8SLen Brown
13995b482a8SLen Brown if (!acpi_gbl_mutex_info[mutex_id].mutex) {
14095b482a8SLen Brown status =
14195b482a8SLen Brown acpi_os_create_mutex(&acpi_gbl_mutex_info[mutex_id].mutex);
14295b482a8SLen Brown acpi_gbl_mutex_info[mutex_id].thread_id =
14395b482a8SLen Brown ACPI_MUTEX_NOT_ACQUIRED;
14495b482a8SLen Brown acpi_gbl_mutex_info[mutex_id].use_count = 0;
14595b482a8SLen Brown }
14695b482a8SLen Brown
14795b482a8SLen Brown return_ACPI_STATUS(status);
14895b482a8SLen Brown }
14995b482a8SLen Brown
15095b482a8SLen Brown /*******************************************************************************
15195b482a8SLen Brown *
15295b482a8SLen Brown * FUNCTION: acpi_ut_delete_mutex
15395b482a8SLen Brown *
154ba494beeSBob Moore * PARAMETERS: mutex_ID - ID of the mutex to be deleted
15595b482a8SLen Brown *
15695b482a8SLen Brown * RETURN: Status
15795b482a8SLen Brown *
15895b482a8SLen Brown * DESCRIPTION: Delete a mutex object.
15995b482a8SLen Brown *
16095b482a8SLen Brown ******************************************************************************/
16195b482a8SLen Brown
acpi_ut_delete_mutex(acpi_mutex_handle mutex_id)1622147d3f0SBob Moore static void acpi_ut_delete_mutex(acpi_mutex_handle mutex_id)
16395b482a8SLen Brown {
16495b482a8SLen Brown
16595b482a8SLen Brown ACPI_FUNCTION_TRACE_U32(ut_delete_mutex, mutex_id);
16695b482a8SLen Brown
16795b482a8SLen Brown acpi_os_delete_mutex(acpi_gbl_mutex_info[mutex_id].mutex);
16895b482a8SLen Brown
16995b482a8SLen Brown acpi_gbl_mutex_info[mutex_id].mutex = NULL;
17095b482a8SLen Brown acpi_gbl_mutex_info[mutex_id].thread_id = ACPI_MUTEX_NOT_ACQUIRED;
17168aafc35SBob Moore
17268aafc35SBob Moore return_VOID;
17395b482a8SLen Brown }
17495b482a8SLen Brown
17595b482a8SLen Brown /*******************************************************************************
17695b482a8SLen Brown *
17795b482a8SLen Brown * FUNCTION: acpi_ut_acquire_mutex
17895b482a8SLen Brown *
179ba494beeSBob Moore * PARAMETERS: mutex_ID - ID of the mutex to be acquired
18095b482a8SLen Brown *
18195b482a8SLen Brown * RETURN: Status
18295b482a8SLen Brown *
18395b482a8SLen Brown * DESCRIPTION: Acquire a mutex object.
18495b482a8SLen Brown *
18595b482a8SLen Brown ******************************************************************************/
18695b482a8SLen Brown
acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id)18795b482a8SLen Brown acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id)
18895b482a8SLen Brown {
18995b482a8SLen Brown acpi_status status;
19095b482a8SLen Brown acpi_thread_id this_thread_id;
19195b482a8SLen Brown
19295b482a8SLen Brown ACPI_FUNCTION_NAME(ut_acquire_mutex);
19395b482a8SLen Brown
19495b482a8SLen Brown if (mutex_id > ACPI_MAX_MUTEX) {
19595b482a8SLen Brown return (AE_BAD_PARAMETER);
19695b482a8SLen Brown }
19795b482a8SLen Brown
19895b482a8SLen Brown this_thread_id = acpi_os_get_thread_id();
19995b482a8SLen Brown
20095b482a8SLen Brown #ifdef ACPI_MUTEX_DEBUG
20195b482a8SLen Brown {
20295b482a8SLen Brown u32 i;
20395b482a8SLen Brown /*
20495b482a8SLen Brown * Mutex debug code, for internal debugging only.
20595b482a8SLen Brown *
20695b482a8SLen Brown * Deadlock prevention. Check if this thread owns any mutexes of value
20795b482a8SLen Brown * greater than or equal to this one. If so, the thread has violated
20895b482a8SLen Brown * the mutex ordering rule. This indicates a coding error somewhere in
20995b482a8SLen Brown * the ACPI subsystem code.
21095b482a8SLen Brown */
21195b482a8SLen Brown for (i = mutex_id; i < ACPI_NUM_MUTEX; i++) {
21295b482a8SLen Brown if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) {
21395b482a8SLen Brown if (i == mutex_id) {
21495b482a8SLen Brown ACPI_ERROR((AE_INFO,
21528eb3fcfSLin Ming "Mutex [%s] already acquired by this thread [%u]",
21695b482a8SLen Brown acpi_ut_get_mutex_name
21795b482a8SLen Brown (mutex_id),
21828eb3fcfSLin Ming (u32)this_thread_id));
21995b482a8SLen Brown
22095b482a8SLen Brown return (AE_ALREADY_ACQUIRED);
22195b482a8SLen Brown }
22295b482a8SLen Brown
22395b482a8SLen Brown ACPI_ERROR((AE_INFO,
22428eb3fcfSLin Ming "Invalid acquire order: Thread %u owns [%s], wants [%s]",
22528eb3fcfSLin Ming (u32)this_thread_id,
22695b482a8SLen Brown acpi_ut_get_mutex_name(i),
22795b482a8SLen Brown acpi_ut_get_mutex_name(mutex_id)));
22895b482a8SLen Brown
22995b482a8SLen Brown return (AE_ACQUIRE_DEADLOCK);
23095b482a8SLen Brown }
23195b482a8SLen Brown }
23295b482a8SLen Brown }
23395b482a8SLen Brown #endif
23495b482a8SLen Brown
23595b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
23628eb3fcfSLin Ming "Thread %u attempting to acquire Mutex [%s]\n",
23728eb3fcfSLin Ming (u32)this_thread_id,
23895b482a8SLen Brown acpi_ut_get_mutex_name(mutex_id)));
23995b482a8SLen Brown
2401fad8738SBob Moore status =
2411fad8738SBob Moore acpi_os_acquire_mutex(acpi_gbl_mutex_info[mutex_id].mutex,
24295b482a8SLen Brown ACPI_WAIT_FOREVER);
24395b482a8SLen Brown if (ACPI_SUCCESS(status)) {
24495b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
24528eb3fcfSLin Ming "Thread %u acquired Mutex [%s]\n",
24628eb3fcfSLin Ming (u32)this_thread_id,
24795b482a8SLen Brown acpi_ut_get_mutex_name(mutex_id)));
24895b482a8SLen Brown
24995b482a8SLen Brown acpi_gbl_mutex_info[mutex_id].use_count++;
25095b482a8SLen Brown acpi_gbl_mutex_info[mutex_id].thread_id = this_thread_id;
25195b482a8SLen Brown } else {
25295b482a8SLen Brown ACPI_EXCEPTION((AE_INFO, status,
253692aa0cfSBob Moore "Thread %u could not acquire Mutex [%s] (0x%X)",
254692aa0cfSBob Moore (u32)this_thread_id,
255692aa0cfSBob Moore acpi_ut_get_mutex_name(mutex_id), mutex_id));
25695b482a8SLen Brown }
25795b482a8SLen Brown
25895b482a8SLen Brown return (status);
25995b482a8SLen Brown }
26095b482a8SLen Brown
26195b482a8SLen Brown /*******************************************************************************
26295b482a8SLen Brown *
26395b482a8SLen Brown * FUNCTION: acpi_ut_release_mutex
26495b482a8SLen Brown *
265ba494beeSBob Moore * PARAMETERS: mutex_ID - ID of the mutex to be released
26695b482a8SLen Brown *
26795b482a8SLen Brown * RETURN: Status
26895b482a8SLen Brown *
26995b482a8SLen Brown * DESCRIPTION: Release a mutex object.
27095b482a8SLen Brown *
27195b482a8SLen Brown ******************************************************************************/
27295b482a8SLen Brown
acpi_ut_release_mutex(acpi_mutex_handle mutex_id)27395b482a8SLen Brown acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id)
27495b482a8SLen Brown {
27595b482a8SLen Brown ACPI_FUNCTION_NAME(ut_release_mutex);
27695b482a8SLen Brown
27728eb3fcfSLin Ming ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Thread %u releasing Mutex [%s]\n",
27842f52843SBob Moore (u32)acpi_os_get_thread_id(),
27995b482a8SLen Brown acpi_ut_get_mutex_name(mutex_id)));
28095b482a8SLen Brown
28195b482a8SLen Brown if (mutex_id > ACPI_MAX_MUTEX) {
28295b482a8SLen Brown return (AE_BAD_PARAMETER);
28395b482a8SLen Brown }
28495b482a8SLen Brown
28595b482a8SLen Brown /*
28695b482a8SLen Brown * Mutex must be acquired in order to release it!
28795b482a8SLen Brown */
28895b482a8SLen Brown if (acpi_gbl_mutex_info[mutex_id].thread_id == ACPI_MUTEX_NOT_ACQUIRED) {
28995b482a8SLen Brown ACPI_ERROR((AE_INFO,
290692aa0cfSBob Moore "Mutex [%s] (0x%X) is not acquired, cannot release",
291692aa0cfSBob Moore acpi_ut_get_mutex_name(mutex_id), mutex_id));
29295b482a8SLen Brown
29395b482a8SLen Brown return (AE_NOT_ACQUIRED);
29495b482a8SLen Brown }
29595b482a8SLen Brown #ifdef ACPI_MUTEX_DEBUG
29695b482a8SLen Brown {
29795b482a8SLen Brown u32 i;
29895b482a8SLen Brown /*
29995b482a8SLen Brown * Mutex debug code, for internal debugging only.
30095b482a8SLen Brown *
30195b482a8SLen Brown * Deadlock prevention. Check if this thread owns any mutexes of value
30295b482a8SLen Brown * greater than this one. If so, the thread has violated the mutex
30395b482a8SLen Brown * ordering rule. This indicates a coding error somewhere in
30495b482a8SLen Brown * the ACPI subsystem code.
30595b482a8SLen Brown */
30695b482a8SLen Brown for (i = mutex_id; i < ACPI_NUM_MUTEX; i++) {
30742f52843SBob Moore if (acpi_gbl_mutex_info[i].thread_id ==
30842f52843SBob Moore acpi_os_get_thread_id()) {
30995b482a8SLen Brown if (i == mutex_id) {
31095b482a8SLen Brown continue;
31195b482a8SLen Brown }
31295b482a8SLen Brown
31395b482a8SLen Brown ACPI_ERROR((AE_INFO,
31495b482a8SLen Brown "Invalid release order: owns [%s], releasing [%s]",
31595b482a8SLen Brown acpi_ut_get_mutex_name(i),
31695b482a8SLen Brown acpi_ut_get_mutex_name(mutex_id)));
31795b482a8SLen Brown
31895b482a8SLen Brown return (AE_RELEASE_DEADLOCK);
31995b482a8SLen Brown }
32095b482a8SLen Brown }
32195b482a8SLen Brown }
32295b482a8SLen Brown #endif
32395b482a8SLen Brown
32495b482a8SLen Brown /* Mark unlocked FIRST */
32595b482a8SLen Brown
32695b482a8SLen Brown acpi_gbl_mutex_info[mutex_id].thread_id = ACPI_MUTEX_NOT_ACQUIRED;
32795b482a8SLen Brown
32895b482a8SLen Brown acpi_os_release_mutex(acpi_gbl_mutex_info[mutex_id].mutex);
32995b482a8SLen Brown return (AE_OK);
33095b482a8SLen Brown }
331