• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/drivers/acpi/acpica/
1/*******************************************************************************
2 *
3 * Module Name: utmutex - local mutex support
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2010, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions, and the following disclaimer,
16 *    without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 *    substantially similar to the "NO WARRANTY" disclaimer below
19 *    ("Disclaimer") and any redistribution must be conditioned upon
20 *    including a substantially similar Disclaimer requirement for further
21 *    binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 *    of any contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include <acpi/acpi.h>
45#include "accommon.h"
46
47#define _COMPONENT          ACPI_UTILITIES
48ACPI_MODULE_NAME("utmutex")
49
50/* Local prototypes */
51static acpi_status acpi_ut_create_mutex(acpi_mutex_handle mutex_id);
52
53static void acpi_ut_delete_mutex(acpi_mutex_handle mutex_id);
54
55/*******************************************************************************
56 *
57 * FUNCTION:    acpi_ut_mutex_initialize
58 *
59 * PARAMETERS:  None.
60 *
61 * RETURN:      Status
62 *
63 * DESCRIPTION: Create the system mutex objects. This includes mutexes,
64 *              spin locks, and reader/writer locks.
65 *
66 ******************************************************************************/
67
68acpi_status acpi_ut_mutex_initialize(void)
69{
70	u32 i;
71	acpi_status status;
72
73	ACPI_FUNCTION_TRACE(ut_mutex_initialize);
74
75	/* Create each of the predefined mutex objects */
76
77	for (i = 0; i < ACPI_NUM_MUTEX; i++) {
78		status = acpi_ut_create_mutex(i);
79		if (ACPI_FAILURE(status)) {
80			return_ACPI_STATUS(status);
81		}
82	}
83
84	/* Create the spinlocks for use at interrupt level */
85
86	spin_lock_init(acpi_gbl_gpe_lock);
87	spin_lock_init(acpi_gbl_hardware_lock);
88
89	/* Create the reader/writer lock for namespace access */
90
91	status = acpi_ut_create_rw_lock(&acpi_gbl_namespace_rw_lock);
92	return_ACPI_STATUS(status);
93}
94
95/*******************************************************************************
96 *
97 * FUNCTION:    acpi_ut_mutex_terminate
98 *
99 * PARAMETERS:  None.
100 *
101 * RETURN:      None.
102 *
103 * DESCRIPTION: Delete all of the system mutex objects. This includes mutexes,
104 *              spin locks, and reader/writer locks.
105 *
106 ******************************************************************************/
107
108void acpi_ut_mutex_terminate(void)
109{
110	u32 i;
111
112	ACPI_FUNCTION_TRACE(ut_mutex_terminate);
113
114	/* Delete each predefined mutex object */
115
116	for (i = 0; i < ACPI_NUM_MUTEX; i++) {
117		acpi_ut_delete_mutex(i);
118	}
119
120	/* Delete the spinlocks */
121
122	acpi_os_delete_lock(acpi_gbl_gpe_lock);
123	acpi_os_delete_lock(acpi_gbl_hardware_lock);
124
125	/* Delete the reader/writer lock */
126
127	acpi_ut_delete_rw_lock(&acpi_gbl_namespace_rw_lock);
128	return_VOID;
129}
130
131/*******************************************************************************
132 *
133 * FUNCTION:    acpi_ut_create_mutex
134 *
135 * PARAMETERS:  mutex_iD        - ID of the mutex to be created
136 *
137 * RETURN:      Status
138 *
139 * DESCRIPTION: Create a mutex object.
140 *
141 ******************************************************************************/
142
143static acpi_status acpi_ut_create_mutex(acpi_mutex_handle mutex_id)
144{
145	acpi_status status = AE_OK;
146
147	ACPI_FUNCTION_TRACE_U32(ut_create_mutex, mutex_id);
148
149	if (!acpi_gbl_mutex_info[mutex_id].mutex) {
150		status =
151		    acpi_os_create_mutex(&acpi_gbl_mutex_info[mutex_id].mutex);
152		acpi_gbl_mutex_info[mutex_id].thread_id =
153		    ACPI_MUTEX_NOT_ACQUIRED;
154		acpi_gbl_mutex_info[mutex_id].use_count = 0;
155	}
156
157	return_ACPI_STATUS(status);
158}
159
160/*******************************************************************************
161 *
162 * FUNCTION:    acpi_ut_delete_mutex
163 *
164 * PARAMETERS:  mutex_iD        - ID of the mutex to be deleted
165 *
166 * RETURN:      Status
167 *
168 * DESCRIPTION: Delete a mutex object.
169 *
170 ******************************************************************************/
171
172static void acpi_ut_delete_mutex(acpi_mutex_handle mutex_id)
173{
174
175	ACPI_FUNCTION_TRACE_U32(ut_delete_mutex, mutex_id);
176
177	acpi_os_delete_mutex(acpi_gbl_mutex_info[mutex_id].mutex);
178
179	acpi_gbl_mutex_info[mutex_id].mutex = NULL;
180	acpi_gbl_mutex_info[mutex_id].thread_id = ACPI_MUTEX_NOT_ACQUIRED;
181}
182
183/*******************************************************************************
184 *
185 * FUNCTION:    acpi_ut_acquire_mutex
186 *
187 * PARAMETERS:  mutex_iD        - ID of the mutex to be acquired
188 *
189 * RETURN:      Status
190 *
191 * DESCRIPTION: Acquire a mutex object.
192 *
193 ******************************************************************************/
194
195acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id)
196{
197	acpi_status status;
198	acpi_thread_id this_thread_id;
199
200	ACPI_FUNCTION_NAME(ut_acquire_mutex);
201
202	if (mutex_id > ACPI_MAX_MUTEX) {
203		return (AE_BAD_PARAMETER);
204	}
205
206	this_thread_id = acpi_os_get_thread_id();
207
208#ifdef ACPI_MUTEX_DEBUG
209	{
210		u32 i;
211		/*
212		 * Mutex debug code, for internal debugging only.
213		 *
214		 * Deadlock prevention.  Check if this thread owns any mutexes of value
215		 * greater than or equal to this one.  If so, the thread has violated
216		 * the mutex ordering rule.  This indicates a coding error somewhere in
217		 * the ACPI subsystem code.
218		 */
219		for (i = mutex_id; i < ACPI_NUM_MUTEX; i++) {
220			if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) {
221				if (i == mutex_id) {
222					ACPI_ERROR((AE_INFO,
223						    "Mutex [%s] already acquired by this thread [%p]",
224						    acpi_ut_get_mutex_name
225						    (mutex_id),
226						    ACPI_CAST_PTR(void,
227								  this_thread_id)));
228
229					return (AE_ALREADY_ACQUIRED);
230				}
231
232				ACPI_ERROR((AE_INFO,
233					    "Invalid acquire order: Thread %p owns [%s], wants [%s]",
234					    ACPI_CAST_PTR(void, this_thread_id),
235					    acpi_ut_get_mutex_name(i),
236					    acpi_ut_get_mutex_name(mutex_id)));
237
238				return (AE_ACQUIRE_DEADLOCK);
239			}
240		}
241	}
242#endif
243
244	ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
245			  "Thread %p attempting to acquire Mutex [%s]\n",
246			  ACPI_CAST_PTR(void, this_thread_id),
247			  acpi_ut_get_mutex_name(mutex_id)));
248
249	status = acpi_os_acquire_mutex(acpi_gbl_mutex_info[mutex_id].mutex,
250				       ACPI_WAIT_FOREVER);
251	if (ACPI_SUCCESS(status)) {
252		ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
253				  "Thread %p acquired Mutex [%s]\n",
254				  ACPI_CAST_PTR(void, this_thread_id),
255				  acpi_ut_get_mutex_name(mutex_id)));
256
257		acpi_gbl_mutex_info[mutex_id].use_count++;
258		acpi_gbl_mutex_info[mutex_id].thread_id = this_thread_id;
259	} else {
260		ACPI_EXCEPTION((AE_INFO, status,
261				"Thread %p could not acquire Mutex [0x%X]",
262				ACPI_CAST_PTR(void, this_thread_id), mutex_id));
263	}
264
265	return (status);
266}
267
268/*******************************************************************************
269 *
270 * FUNCTION:    acpi_ut_release_mutex
271 *
272 * PARAMETERS:  mutex_iD        - ID of the mutex to be released
273 *
274 * RETURN:      Status
275 *
276 * DESCRIPTION: Release a mutex object.
277 *
278 ******************************************************************************/
279
280acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id)
281{
282	ACPI_FUNCTION_NAME(ut_release_mutex);
283
284	ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Thread %p releasing Mutex [%s]\n",
285			  ACPI_CAST_PTR(void, acpi_os_get_thread_id()),
286			  acpi_ut_get_mutex_name(mutex_id)));
287
288	if (mutex_id > ACPI_MAX_MUTEX) {
289		return (AE_BAD_PARAMETER);
290	}
291
292	/*
293	 * Mutex must be acquired in order to release it!
294	 */
295	if (acpi_gbl_mutex_info[mutex_id].thread_id == ACPI_MUTEX_NOT_ACQUIRED) {
296		ACPI_ERROR((AE_INFO,
297			    "Mutex [0x%X] is not acquired, cannot release",
298			    mutex_id));
299
300		return (AE_NOT_ACQUIRED);
301	}
302#ifdef ACPI_MUTEX_DEBUG
303	{
304		u32 i;
305		/*
306		 * Mutex debug code, for internal debugging only.
307		 *
308		 * Deadlock prevention.  Check if this thread owns any mutexes of value
309		 * greater than this one.  If so, the thread has violated the mutex
310		 * ordering rule.  This indicates a coding error somewhere in
311		 * the ACPI subsystem code.
312		 */
313		for (i = mutex_id; i < ACPI_NUM_MUTEX; i++) {
314			if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) {
315				if (i == mutex_id) {
316					continue;
317				}
318
319				ACPI_ERROR((AE_INFO,
320					    "Invalid release order: owns [%s], releasing [%s]",
321					    acpi_ut_get_mutex_name(i),
322					    acpi_ut_get_mutex_name(mutex_id)));
323
324				return (AE_RELEASE_DEADLOCK);
325			}
326		}
327	}
328#endif
329
330	/* Mark unlocked FIRST */
331
332	acpi_gbl_mutex_info[mutex_id].thread_id = ACPI_MUTEX_NOT_ACQUIRED;
333
334	acpi_os_release_mutex(acpi_gbl_mutex_info[mutex_id].mutex);
335	return (AE_OK);
336}
337