xref: /openbmc/linux/drivers/acpi/acpica/utmutex.c (revision 3a83e4e6)
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /*******************************************************************************
3  *
4  * Module Name: utmutex - local mutex support
5  *
6  ******************************************************************************/
7 
8 #include <acpi/acpi.h>
9 #include "accommon.h"
10 
11 #define _COMPONENT          ACPI_UTILITIES
12 ACPI_MODULE_NAME("utmutex")
13 
14 /* Local prototypes */
15 static acpi_status acpi_ut_create_mutex(acpi_mutex_handle mutex_id);
16 
17 static void acpi_ut_delete_mutex(acpi_mutex_handle mutex_id);
18 
19 /*******************************************************************************
20  *
21  * FUNCTION:    acpi_ut_mutex_initialize
22  *
23  * PARAMETERS:  None.
24  *
25  * RETURN:      Status
26  *
27  * DESCRIPTION: Create the system mutex objects. This includes mutexes,
28  *              spin locks, and reader/writer locks.
29  *
30  ******************************************************************************/
31 
32 acpi_status acpi_ut_mutex_initialize(void)
33 {
34 	u32 i;
35 	acpi_status status;
36 
37 	ACPI_FUNCTION_TRACE(ut_mutex_initialize);
38 
39 	/* Create each of the predefined mutex objects */
40 
41 	for (i = 0; i < ACPI_NUM_MUTEX; i++) {
42 		status = acpi_ut_create_mutex(i);
43 		if (ACPI_FAILURE(status)) {
44 			return_ACPI_STATUS(status);
45 		}
46 	}
47 
48 	/* Create the spinlocks for use at interrupt level or for speed */
49 
50 	status = acpi_os_create_lock (&acpi_gbl_gpe_lock);
51 	if (ACPI_FAILURE (status)) {
52 		return_ACPI_STATUS (status);
53 	}
54 
55 	status = acpi_os_create_raw_lock(&acpi_gbl_hardware_lock);
56 	if (ACPI_FAILURE (status)) {
57 		return_ACPI_STATUS (status);
58 	}
59 
60 	status = acpi_os_create_lock(&acpi_gbl_reference_count_lock);
61 	if (ACPI_FAILURE(status)) {
62 		return_ACPI_STATUS(status);
63 	}
64 
65 	/* Mutex for _OSI support */
66 
67 	status = acpi_os_create_mutex(&acpi_gbl_osi_mutex);
68 	if (ACPI_FAILURE(status)) {
69 		return_ACPI_STATUS(status);
70 	}
71 
72 	/* Create the reader/writer lock for namespace access */
73 
74 	status = acpi_ut_create_rw_lock(&acpi_gbl_namespace_rw_lock);
75 	if (ACPI_FAILURE(status)) {
76 		return_ACPI_STATUS(status);
77 	}
78 
79 	return_ACPI_STATUS(status);
80 }
81 
82 /*******************************************************************************
83  *
84  * FUNCTION:    acpi_ut_mutex_terminate
85  *
86  * PARAMETERS:  None.
87  *
88  * RETURN:      None.
89  *
90  * DESCRIPTION: Delete all of the system mutex objects. This includes mutexes,
91  *              spin locks, and reader/writer locks.
92  *
93  ******************************************************************************/
94 
95 void acpi_ut_mutex_terminate(void)
96 {
97 	u32 i;
98 
99 	ACPI_FUNCTION_TRACE(ut_mutex_terminate);
100 
101 	/* Delete each predefined mutex object */
102 
103 	for (i = 0; i < ACPI_NUM_MUTEX; i++) {
104 		acpi_ut_delete_mutex(i);
105 	}
106 
107 	acpi_os_delete_mutex(acpi_gbl_osi_mutex);
108 
109 	/* Delete the spinlocks */
110 
111 	acpi_os_delete_lock(acpi_gbl_gpe_lock);
112 	acpi_os_delete_raw_lock(acpi_gbl_hardware_lock);
113 	acpi_os_delete_lock(acpi_gbl_reference_count_lock);
114 
115 	/* Delete the reader/writer lock */
116 
117 	acpi_ut_delete_rw_lock(&acpi_gbl_namespace_rw_lock);
118 	return_VOID;
119 }
120 
121 /*******************************************************************************
122  *
123  * FUNCTION:    acpi_ut_create_mutex
124  *
125  * PARAMETERS:  mutex_ID        - ID of the mutex to be created
126  *
127  * RETURN:      Status
128  *
129  * DESCRIPTION: Create a mutex object.
130  *
131  ******************************************************************************/
132 
133 static acpi_status acpi_ut_create_mutex(acpi_mutex_handle mutex_id)
134 {
135 	acpi_status status = AE_OK;
136 
137 	ACPI_FUNCTION_TRACE_U32(ut_create_mutex, mutex_id);
138 
139 	if (!acpi_gbl_mutex_info[mutex_id].mutex) {
140 		status =
141 		    acpi_os_create_mutex(&acpi_gbl_mutex_info[mutex_id].mutex);
142 		acpi_gbl_mutex_info[mutex_id].thread_id =
143 		    ACPI_MUTEX_NOT_ACQUIRED;
144 		acpi_gbl_mutex_info[mutex_id].use_count = 0;
145 	}
146 
147 	return_ACPI_STATUS(status);
148 }
149 
150 /*******************************************************************************
151  *
152  * FUNCTION:    acpi_ut_delete_mutex
153  *
154  * PARAMETERS:  mutex_ID        - ID of the mutex to be deleted
155  *
156  * RETURN:      Status
157  *
158  * DESCRIPTION: Delete a mutex object.
159  *
160  ******************************************************************************/
161 
162 static void acpi_ut_delete_mutex(acpi_mutex_handle mutex_id)
163 {
164 
165 	ACPI_FUNCTION_TRACE_U32(ut_delete_mutex, mutex_id);
166 
167 	acpi_os_delete_mutex(acpi_gbl_mutex_info[mutex_id].mutex);
168 
169 	acpi_gbl_mutex_info[mutex_id].mutex = NULL;
170 	acpi_gbl_mutex_info[mutex_id].thread_id = ACPI_MUTEX_NOT_ACQUIRED;
171 
172 	return_VOID;
173 }
174 
175 /*******************************************************************************
176  *
177  * FUNCTION:    acpi_ut_acquire_mutex
178  *
179  * PARAMETERS:  mutex_ID        - ID of the mutex to be acquired
180  *
181  * RETURN:      Status
182  *
183  * DESCRIPTION: Acquire a mutex object.
184  *
185  ******************************************************************************/
186 
187 acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id)
188 {
189 	acpi_status status;
190 	acpi_thread_id this_thread_id;
191 
192 	ACPI_FUNCTION_NAME(ut_acquire_mutex);
193 
194 	if (mutex_id > ACPI_MAX_MUTEX) {
195 		return (AE_BAD_PARAMETER);
196 	}
197 
198 	this_thread_id = acpi_os_get_thread_id();
199 
200 #ifdef ACPI_MUTEX_DEBUG
201 	{
202 		u32 i;
203 		/*
204 		 * Mutex debug code, for internal debugging only.
205 		 *
206 		 * Deadlock prevention. Check if this thread owns any mutexes of value
207 		 * greater than or equal to this one. If so, the thread has violated
208 		 * the mutex ordering rule. This indicates a coding error somewhere in
209 		 * the ACPI subsystem code.
210 		 */
211 		for (i = mutex_id; i < ACPI_NUM_MUTEX; i++) {
212 			if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) {
213 				if (i == mutex_id) {
214 					ACPI_ERROR((AE_INFO,
215 						    "Mutex [%s] already acquired by this thread [%u]",
216 						    acpi_ut_get_mutex_name
217 						    (mutex_id),
218 						    (u32)this_thread_id));
219 
220 					return (AE_ALREADY_ACQUIRED);
221 				}
222 
223 				ACPI_ERROR((AE_INFO,
224 					    "Invalid acquire order: Thread %u owns [%s], wants [%s]",
225 					    (u32)this_thread_id,
226 					    acpi_ut_get_mutex_name(i),
227 					    acpi_ut_get_mutex_name(mutex_id)));
228 
229 				return (AE_ACQUIRE_DEADLOCK);
230 			}
231 		}
232 	}
233 #endif
234 
235 	ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
236 			  "Thread %u attempting to acquire Mutex [%s]\n",
237 			  (u32)this_thread_id,
238 			  acpi_ut_get_mutex_name(mutex_id)));
239 
240 	status =
241 	    acpi_os_acquire_mutex(acpi_gbl_mutex_info[mutex_id].mutex,
242 				  ACPI_WAIT_FOREVER);
243 	if (ACPI_SUCCESS(status)) {
244 		ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
245 				  "Thread %u acquired Mutex [%s]\n",
246 				  (u32)this_thread_id,
247 				  acpi_ut_get_mutex_name(mutex_id)));
248 
249 		acpi_gbl_mutex_info[mutex_id].use_count++;
250 		acpi_gbl_mutex_info[mutex_id].thread_id = this_thread_id;
251 	} else {
252 		ACPI_EXCEPTION((AE_INFO, status,
253 				"Thread %u could not acquire Mutex [%s] (0x%X)",
254 				(u32)this_thread_id,
255 				acpi_ut_get_mutex_name(mutex_id), mutex_id));
256 	}
257 
258 	return (status);
259 }
260 
261 /*******************************************************************************
262  *
263  * FUNCTION:    acpi_ut_release_mutex
264  *
265  * PARAMETERS:  mutex_ID        - ID of the mutex to be released
266  *
267  * RETURN:      Status
268  *
269  * DESCRIPTION: Release a mutex object.
270  *
271  ******************************************************************************/
272 
273 acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id)
274 {
275 	ACPI_FUNCTION_NAME(ut_release_mutex);
276 
277 	ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Thread %u releasing Mutex [%s]\n",
278 			  (u32)acpi_os_get_thread_id(),
279 			  acpi_ut_get_mutex_name(mutex_id)));
280 
281 	if (mutex_id > ACPI_MAX_MUTEX) {
282 		return (AE_BAD_PARAMETER);
283 	}
284 
285 	/*
286 	 * Mutex must be acquired in order to release it!
287 	 */
288 	if (acpi_gbl_mutex_info[mutex_id].thread_id == ACPI_MUTEX_NOT_ACQUIRED) {
289 		ACPI_ERROR((AE_INFO,
290 			    "Mutex [%s] (0x%X) is not acquired, cannot release",
291 			    acpi_ut_get_mutex_name(mutex_id), mutex_id));
292 
293 		return (AE_NOT_ACQUIRED);
294 	}
295 #ifdef ACPI_MUTEX_DEBUG
296 	{
297 		u32 i;
298 		/*
299 		 * Mutex debug code, for internal debugging only.
300 		 *
301 		 * Deadlock prevention. Check if this thread owns any mutexes of value
302 		 * greater than this one. If so, the thread has violated the mutex
303 		 * ordering rule. This indicates a coding error somewhere in
304 		 * the ACPI subsystem code.
305 		 */
306 		for (i = mutex_id; i < ACPI_NUM_MUTEX; i++) {
307 			if (acpi_gbl_mutex_info[i].thread_id ==
308 			    acpi_os_get_thread_id()) {
309 				if (i == mutex_id) {
310 					continue;
311 				}
312 
313 				ACPI_ERROR((AE_INFO,
314 					    "Invalid release order: owns [%s], releasing [%s]",
315 					    acpi_ut_get_mutex_name(i),
316 					    acpi_ut_get_mutex_name(mutex_id)));
317 
318 				return (AE_RELEASE_DEADLOCK);
319 			}
320 		}
321 	}
322 #endif
323 
324 	/* Mark unlocked FIRST */
325 
326 	acpi_gbl_mutex_info[mutex_id].thread_id = ACPI_MUTEX_NOT_ACQUIRED;
327 
328 	acpi_os_release_mutex(acpi_gbl_mutex_info[mutex_id].mutex);
329 	return (AE_OK);
330 }
331