aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBob Moore <robert.moore@intel.com>2008-04-10 11:06:37 -0400
committerLen Brown <len.brown@intel.com>2008-04-22 14:29:21 -0400
commitba886cd4ac957608777fbc8d137f6b9f0450e775 (patch)
treed7dabaa586af41c293977443ee20df6b6b13d171
parentf654ecbfacb47d20e8cac087bbada1b947db846b (diff)
ACPICA: Update for mutiple global lock acquisitions by same thread
Allows AcpiAcquireGlobalLock external interface to be called multiple times by the same thread. Allows use of AML fields that require the global lock while the running AML is already holding the global lock. Signed-off-by: Bob Moore <robert.moore@intel.com> Signed-off-by: Alexey Starikovskiy <astarikovskiy@suse.de> Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r--drivers/acpi/dispatcher/dsmethod.c12
-rw-r--r--drivers/acpi/events/evmisc.c11
-rw-r--r--drivers/acpi/events/evxface.c26
-rw-r--r--drivers/acpi/executer/exfield.c24
-rw-r--r--drivers/acpi/executer/exmutex.c194
-rw-r--r--drivers/acpi/executer/exutils.c58
-rw-r--r--drivers/acpi/namespace/nsaccess.c3
-rw-r--r--drivers/acpi/utilities/utdelete.c2
-rw-r--r--include/acpi/acglobal.h20
-rw-r--r--include/acpi/acinterp.h11
-rw-r--r--include/acpi/acobject.h3
11 files changed, 219 insertions, 145 deletions
diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c
index 1cbe61905824..c50c0cd5d717 100644
--- a/drivers/acpi/dispatcher/dsmethod.c
+++ b/drivers/acpi/dispatcher/dsmethod.c
@@ -232,9 +232,9 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node,
232 * recursive call. 232 * recursive call.
233 */ 233 */
234 if (!walk_state || 234 if (!walk_state ||
235 !obj_desc->method.mutex->mutex.owner_thread || 235 !obj_desc->method.mutex->mutex.thread_id ||
236 (walk_state->thread != 236 (walk_state->thread->thread_id !=
237 obj_desc->method.mutex->mutex.owner_thread)) { 237 obj_desc->method.mutex->mutex.thread_id)) {
238 /* 238 /*
239 * Acquire the method mutex. This releases the interpreter if we 239 * Acquire the method mutex. This releases the interpreter if we
240 * block (and reacquires it before it returns) 240 * block (and reacquires it before it returns)
@@ -254,8 +254,8 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node,
254 original_sync_level = 254 original_sync_level =
255 walk_state->thread->current_sync_level; 255 walk_state->thread->current_sync_level;
256 256
257 obj_desc->method.mutex->mutex.owner_thread = 257 obj_desc->method.mutex->mutex.thread_id =
258 walk_state->thread; 258 walk_state->thread->thread_id;
259 walk_state->thread->current_sync_level = 259 walk_state->thread->current_sync_level =
260 obj_desc->method.sync_level; 260 obj_desc->method.sync_level;
261 } else { 261 } else {
@@ -569,7 +569,7 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
569 569
570 acpi_os_release_mutex(method_desc->method.mutex->mutex. 570 acpi_os_release_mutex(method_desc->method.mutex->mutex.
571 os_mutex); 571 os_mutex);
572 method_desc->method.mutex->mutex.owner_thread = NULL; 572 method_desc->method.mutex->mutex.thread_id = 0;
573 } 573 }
574 } 574 }
575 575
diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c
index 21cb749d0c75..2d34663dc1ed 100644
--- a/drivers/acpi/events/evmisc.c
+++ b/drivers/acpi/events/evmisc.c
@@ -439,7 +439,8 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout)
439 * Only one thread can acquire the GL at a time, the global_lock_mutex 439 * Only one thread can acquire the GL at a time, the global_lock_mutex
440 * enforces this. This interface releases the interpreter if we must wait. 440 * enforces this. This interface releases the interpreter if we must wait.
441 */ 441 */
442 status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, 0); 442 status = acpi_ex_system_wait_mutex(
443 acpi_gbl_global_lock_mutex->mutex.os_mutex, 0);
443 if (status == AE_TIME) { 444 if (status == AE_TIME) {
444 if (acpi_ev_global_lock_thread_id == acpi_os_get_thread_id()) { 445 if (acpi_ev_global_lock_thread_id == acpi_os_get_thread_id()) {
445 acpi_ev_global_lock_acquired++; 446 acpi_ev_global_lock_acquired++;
@@ -448,9 +449,9 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout)
448 } 449 }
449 450
450 if (ACPI_FAILURE(status)) { 451 if (ACPI_FAILURE(status)) {
451 status = 452 status = acpi_ex_system_wait_mutex(
452 acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, 453 acpi_gbl_global_lock_mutex->mutex.os_mutex,
453 timeout); 454 timeout);
454 } 455 }
455 if (ACPI_FAILURE(status)) { 456 if (ACPI_FAILURE(status)) {
456 return_ACPI_STATUS(status); 457 return_ACPI_STATUS(status);
@@ -555,7 +556,7 @@ acpi_status acpi_ev_release_global_lock(void)
555 /* Release the local GL mutex */ 556 /* Release the local GL mutex */
556 acpi_ev_global_lock_thread_id = NULL; 557 acpi_ev_global_lock_thread_id = NULL;
557 acpi_ev_global_lock_acquired = 0; 558 acpi_ev_global_lock_acquired = 0;
558 acpi_os_release_mutex(acpi_gbl_global_lock_mutex); 559 acpi_os_release_mutex(acpi_gbl_global_lock_mutex->mutex.os_mutex);
559 return_ACPI_STATUS(status); 560 return_ACPI_STATUS(status);
560} 561}
561 562
diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c
index 6d866a01f5f4..dbf34a5fc1e0 100644
--- a/drivers/acpi/events/evxface.c
+++ b/drivers/acpi/events/evxface.c
@@ -758,6 +758,12 @@ ACPI_EXPORT_SYMBOL(acpi_remove_gpe_handler)
758 * 758 *
759 * DESCRIPTION: Acquire the ACPI Global Lock 759 * DESCRIPTION: Acquire the ACPI Global Lock
760 * 760 *
761 * Note: Allows callers with the same thread ID to acquire the global lock
762 * multiple times. In other words, externally, the behavior of the global lock
763 * is identical to an AML mutex. On the first acquire, a new handle is
764 * returned. On any subsequent calls to acquire by the same thread, the same
765 * handle is returned.
766 *
761 ******************************************************************************/ 767 ******************************************************************************/
762acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle) 768acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle)
763{ 769{
@@ -770,14 +776,26 @@ acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle)
770 /* Must lock interpreter to prevent race conditions */ 776 /* Must lock interpreter to prevent race conditions */
771 777
772 acpi_ex_enter_interpreter(); 778 acpi_ex_enter_interpreter();
773 status = acpi_ev_acquire_global_lock(timeout); 779
774 acpi_ex_exit_interpreter(); 780 status = acpi_ex_acquire_mutex_object(timeout,
781 acpi_gbl_global_lock_mutex,
782 acpi_os_get_thread_id());
775 783
776 if (ACPI_SUCCESS(status)) { 784 if (ACPI_SUCCESS(status)) {
777 acpi_gbl_global_lock_handle++; 785 /*
786 * If this was the first acquisition of the Global Lock by this thread,
787 * create a new handle. Otherwise, return the existing handle.
788 */
789 if (acpi_gbl_global_lock_mutex->mutex.acquisition_depth == 1) {
790 acpi_gbl_global_lock_handle++;
791 }
792
793 /* Return the global lock handle */
794
778 *handle = acpi_gbl_global_lock_handle; 795 *handle = acpi_gbl_global_lock_handle;
779 } 796 }
780 797
798 acpi_ex_exit_interpreter();
781 return (status); 799 return (status);
782} 800}
783 801
@@ -802,7 +820,7 @@ acpi_status acpi_release_global_lock(u32 handle)
802 return (AE_NOT_ACQUIRED); 820 return (AE_NOT_ACQUIRED);
803 } 821 }
804 822
805 status = acpi_ev_release_global_lock(); 823 status = acpi_ex_release_mutex_object(acpi_gbl_global_lock_mutex);
806 return (status); 824 return (status);
807} 825}
808 826
diff --git a/drivers/acpi/executer/exfield.c b/drivers/acpi/executer/exfield.c
index 2d88a3d8d1ad..e66b367c4fb6 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,
71 union acpi_operand_object *buffer_desc; 71 union acpi_operand_object *buffer_desc;
72 acpi_size length; 72 acpi_size length;
73 void *buffer; 73 void *buffer;
74 u8 locked;
75 74
76 ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc); 75 ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc);
77 76
@@ -111,9 +110,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
111 110
112 /* Lock entire transaction if requested */ 111 /* Lock entire transaction if requested */
113 112
114 locked = 113 acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
115 acpi_ex_acquire_global_lock(obj_desc->common_field.
116 field_flags);
117 114
118 /* 115 /*
119 * Perform the read. 116 * Perform the read.
@@ -125,7 +122,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
125 buffer.pointer), 122 buffer.pointer),
126 ACPI_READ | (obj_desc->field. 123 ACPI_READ | (obj_desc->field.
127 attribute << 16)); 124 attribute << 16));
128 acpi_ex_release_global_lock(locked); 125 acpi_ex_release_global_lock();
129 goto exit; 126 goto exit;
130 } 127 }
131 128
@@ -175,13 +172,12 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
175 172
176 /* Lock entire transaction if requested */ 173 /* Lock entire transaction if requested */
177 174
178 locked = 175 acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
179 acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
180 176
181 /* Read from the field */ 177 /* Read from the field */
182 178
183 status = acpi_ex_extract_from_field(obj_desc, buffer, (u32) length); 179 status = acpi_ex_extract_from_field(obj_desc, buffer, (u32) length);
184 acpi_ex_release_global_lock(locked); 180 acpi_ex_release_global_lock();
185 181
186 exit: 182 exit:
187 if (ACPI_FAILURE(status)) { 183 if (ACPI_FAILURE(status)) {
@@ -217,7 +213,6 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
217 u32 required_length; 213 u32 required_length;
218 void *buffer; 214 void *buffer;
219 void *new_buffer; 215 void *new_buffer;
220 u8 locked;
221 union acpi_operand_object *buffer_desc; 216 union acpi_operand_object *buffer_desc;
222 217
223 ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc); 218 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,
278 273
279 /* Lock entire transaction if requested */ 274 /* Lock entire transaction if requested */
280 275
281 locked = 276 acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
282 acpi_ex_acquire_global_lock(obj_desc->common_field.
283 field_flags);
284 277
285 /* 278 /*
286 * Perform the write (returns status and perhaps data in the 279 * 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,
291 (acpi_integer *) buffer, 284 (acpi_integer *) buffer,
292 ACPI_WRITE | (obj_desc->field. 285 ACPI_WRITE | (obj_desc->field.
293 attribute << 16)); 286 attribute << 16));
294 acpi_ex_release_global_lock(locked); 287 acpi_ex_release_global_lock();
295 288
296 *result_desc = buffer_desc; 289 *result_desc = buffer_desc;
297 return_ACPI_STATUS(status); 290 return_ACPI_STATUS(status);
@@ -366,13 +359,12 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
366 359
367 /* Lock entire transaction if requested */ 360 /* Lock entire transaction if requested */
368 361
369 locked = 362 acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
370 acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
371 363
372 /* Write to the field */ 364 /* Write to the field */
373 365
374 status = acpi_ex_insert_into_field(obj_desc, buffer, length); 366 status = acpi_ex_insert_into_field(obj_desc, buffer, length);
375 acpi_ex_release_global_lock(locked); 367 acpi_ex_release_global_lock();
376 368
377 /* Free temporary buffer if we used one */ 369 /* Free temporary buffer if we used one */
378 370
diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c
index 6748e3ef0997..0bebe751aac5 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,
126 126
127/******************************************************************************* 127/*******************************************************************************
128 * 128 *
129 * FUNCTION: acpi_ex_acquire_mutex_object
130 *
131 * PARAMETERS: time_desc - Timeout in milliseconds
132 * obj_desc - Mutex object
133 * Thread - Current thread state
134 *
135 * RETURN: Status
136 *
137 * DESCRIPTION: Acquire an AML mutex, low-level interface
138 *
139 ******************************************************************************/
140
141acpi_status
142acpi_ex_acquire_mutex_object(u16 timeout,
143 union acpi_operand_object *obj_desc,
144 acpi_thread_id thread_id)
145{
146 acpi_status status;
147
148 ACPI_FUNCTION_TRACE_PTR(ex_acquire_mutex_object, obj_desc);
149
150 /* Support for multiple acquires by the owning thread */
151
152 if (obj_desc->mutex.thread_id == thread_id) {
153 /*
154 * The mutex is already owned by this thread, just increment the
155 * acquisition depth
156 */
157 obj_desc->mutex.acquisition_depth++;
158 return_ACPI_STATUS(AE_OK);
159 }
160
161 /* Acquire the mutex, wait if necessary. Special case for Global Lock */
162
163 if (obj_desc == acpi_gbl_global_lock_mutex) {
164 status = acpi_ev_acquire_global_lock(timeout);
165 } else {
166 status = acpi_ex_system_wait_mutex(obj_desc->mutex.os_mutex,
167 timeout);
168 }
169
170 if (ACPI_FAILURE(status)) {
171
172 /* Includes failure from a timeout on time_desc */
173
174 return_ACPI_STATUS(status);
175 }
176
177 /* Have the mutex: update mutex and save the sync_level */
178
179 obj_desc->mutex.thread_id = thread_id;
180 obj_desc->mutex.acquisition_depth = 1;
181 obj_desc->mutex.original_sync_level = 0;
182 obj_desc->mutex.owner_thread = NULL; /* Used only for AML Acquire() */
183
184 return_ACPI_STATUS(AE_OK);
185}
186
187/*******************************************************************************
188 *
129 * FUNCTION: acpi_ex_acquire_mutex 189 * FUNCTION: acpi_ex_acquire_mutex
130 * 190 *
131 * PARAMETERS: time_desc - Timeout integer 191 * PARAMETERS: time_desc - Timeout integer
@@ -161,7 +221,7 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc,
161 } 221 }
162 222
163 /* 223 /*
164 * Current Sync must be less than or equal to the sync level of the 224 * Current Sync level must be less than or equal to the sync level of the
165 * mutex. This mechanism provides some deadlock prevention 225 * mutex. This mechanism provides some deadlock prevention
166 */ 226 */
167 if (walk_state->thread->current_sync_level > obj_desc->mutex.sync_level) { 227 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,
172 return_ACPI_STATUS(AE_AML_MUTEX_ORDER); 232 return_ACPI_STATUS(AE_AML_MUTEX_ORDER);
173 } 233 }
174 234
175 /* Support for multiple acquires by the owning thread */ 235 status = acpi_ex_acquire_mutex_object((u16) time_desc->integer.value,
236 obj_desc,
237 walk_state->thread->thread_id);
238 if (ACPI_SUCCESS(status) && obj_desc->mutex.acquisition_depth == 1) {
239 obj_desc->mutex.owner_thread = walk_state->thread;
240 obj_desc->mutex.original_sync_level =
241 walk_state->thread->current_sync_level;
242 walk_state->thread->current_sync_level =
243 obj_desc->mutex.sync_level;
176 244
177 if (obj_desc->mutex.owner_thread) { 245 /* Link the mutex to the current thread for force-unlock at method exit */
178 if (obj_desc->mutex.owner_thread->thread_id == 246
179 walk_state->thread->thread_id) { 247 acpi_ex_link_mutex(obj_desc, walk_state->thread);
180 /*
181 * The mutex is already owned by this thread, just increment the
182 * acquisition depth
183 */
184 obj_desc->mutex.acquisition_depth++;
185 return_ACPI_STATUS(AE_OK);
186 }
187 } 248 }
188 249
189 /* Acquire the mutex, wait if necessary. Special case for Global Lock */ 250 return_ACPI_STATUS(status);
251}
190 252
191 if (obj_desc->mutex.os_mutex == acpi_gbl_global_lock_mutex) { 253/*******************************************************************************
192 status = 254 *
193 acpi_ev_acquire_global_lock((u16) time_desc->integer.value); 255 * FUNCTION: acpi_ex_release_mutex_object
194 } else { 256 *
195 status = acpi_ex_system_wait_mutex(obj_desc->mutex.os_mutex, 257 * PARAMETERS: obj_desc - The object descriptor for this op
196 (u16) time_desc->integer. 258 *
197 value); 259 * RETURN: Status
198 } 260 *
261 * DESCRIPTION: Release a previously acquired Mutex, low level interface.
262 *
263 ******************************************************************************/
199 264
200 if (ACPI_FAILURE(status)) { 265acpi_status acpi_ex_release_mutex_object(union acpi_operand_object *obj_desc)
266{
267 acpi_status status = AE_OK;
201 268
202 /* Includes failure from a timeout on time_desc */ 269 ACPI_FUNCTION_TRACE(ex_release_mutex_object);
203 270
204 return_ACPI_STATUS(status); 271 /* Match multiple Acquires with multiple Releases */
272
273 obj_desc->mutex.acquisition_depth--;
274 if (obj_desc->mutex.acquisition_depth != 0) {
275
276 /* Just decrement the depth and return */
277
278 return_ACPI_STATUS(AE_OK);
205 } 279 }
206 280
207 /* Have the mutex: update mutex and walk info and save the sync_level */ 281 if (obj_desc->mutex.owner_thread) {
208 282
209 obj_desc->mutex.owner_thread = walk_state->thread; 283 /* Unlink the mutex from the owner's list */
210 obj_desc->mutex.acquisition_depth = 1; 284
211 obj_desc->mutex.original_sync_level = 285 acpi_ex_unlink_mutex(obj_desc);
212 walk_state->thread->current_sync_level; 286 obj_desc->mutex.owner_thread = NULL;
287 }
213 288
214 walk_state->thread->current_sync_level = obj_desc->mutex.sync_level; 289 /* Release the mutex, special case for Global Lock */
215 290
216 /* Link the mutex to the current thread for force-unlock at method exit */ 291 if (obj_desc == acpi_gbl_global_lock_mutex) {
292 status = acpi_ev_release_global_lock();
293 } else {
294 acpi_os_release_mutex(obj_desc->mutex.os_mutex);
295 }
217 296
218 acpi_ex_link_mutex(obj_desc, walk_state->thread); 297 obj_desc->mutex.thread_id = 0;
219 return_ACPI_STATUS(AE_OK); 298 return_ACPI_STATUS(status);
220} 299}
221 300
222/******************************************************************************* 301/*******************************************************************************
@@ -253,22 +332,13 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
253 return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED); 332 return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED);
254 } 333 }
255 334
256 /* Sanity check: we must have a valid thread ID */
257
258 if (!walk_state->thread) {
259 ACPI_ERROR((AE_INFO,
260 "Cannot release Mutex [%4.4s], null thread info",
261 acpi_ut_get_node_name(obj_desc->mutex.node)));
262 return_ACPI_STATUS(AE_AML_INTERNAL);
263 }
264
265 /* 335 /*
266 * The Mutex is owned, but this thread must be the owner. 336 * The Mutex is owned, but this thread must be the owner.
267 * Special case for Global Lock, any thread can release 337 * Special case for Global Lock, any thread can release
268 */ 338 */
269 if ((obj_desc->mutex.owner_thread->thread_id != 339 if ((obj_desc->mutex.owner_thread->thread_id !=
270 walk_state->thread->thread_id) 340 walk_state->thread->thread_id)
271 && (obj_desc->mutex.os_mutex != acpi_gbl_global_lock_mutex)) { 341 && (obj_desc != acpi_gbl_global_lock_mutex)) {
272 ACPI_ERROR((AE_INFO, 342 ACPI_ERROR((AE_INFO,
273 "Thread %lX cannot release Mutex [%4.4s] acquired by thread %lX", 343 "Thread %lX cannot release Mutex [%4.4s] acquired by thread %lX",
274 (unsigned long)walk_state->thread->thread_id, 344 (unsigned long)walk_state->thread->thread_id,
@@ -278,6 +348,15 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
278 return_ACPI_STATUS(AE_AML_NOT_OWNER); 348 return_ACPI_STATUS(AE_AML_NOT_OWNER);
279 } 349 }
280 350
351 /* Sanity check: we must have a valid thread ID */
352
353 if (!walk_state->thread) {
354 ACPI_ERROR((AE_INFO,
355 "Cannot release Mutex [%4.4s], null thread info",
356 acpi_ut_get_node_name(obj_desc->mutex.node)));
357 return_ACPI_STATUS(AE_AML_INTERNAL);
358 }
359
281 /* 360 /*
282 * The sync level of the mutex must be less than or equal to the current 361 * The sync level of the mutex must be less than or equal to the current
283 * sync level 362 * sync level
@@ -289,34 +368,12 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
289 return_ACPI_STATUS(AE_AML_MUTEX_ORDER); 368 return_ACPI_STATUS(AE_AML_MUTEX_ORDER);
290 } 369 }
291 370
292 /* Match multiple Acquires with multiple Releases */ 371 status = acpi_ex_release_mutex_object(obj_desc);
293
294 obj_desc->mutex.acquisition_depth--;
295 if (obj_desc->mutex.acquisition_depth != 0) {
296
297 /* Just decrement the depth and return */
298
299 return_ACPI_STATUS(AE_OK);
300 }
301
302 /* Unlink the mutex from the owner's list */
303 372
304 acpi_ex_unlink_mutex(obj_desc); 373 /* Restore sync_level */
305
306 /* Release the mutex, special case for Global Lock */
307 374
308 if (obj_desc->mutex.os_mutex == acpi_gbl_global_lock_mutex) {
309 status = acpi_ev_release_global_lock();
310 } else {
311 acpi_os_release_mutex(obj_desc->mutex.os_mutex);
312 }
313
314 /* Update the mutex and restore sync_level */
315
316 obj_desc->mutex.owner_thread = NULL;
317 walk_state->thread->current_sync_level = 375 walk_state->thread->current_sync_level =
318 obj_desc->mutex.original_sync_level; 376 obj_desc->mutex.original_sync_level;
319
320 return_ACPI_STATUS(status); 377 return_ACPI_STATUS(status);
321} 378}
322 379
@@ -357,7 +414,7 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread)
357 414
358 /* Release the mutex, special case for Global Lock */ 415 /* Release the mutex, special case for Global Lock */
359 416
360 if (obj_desc->mutex.os_mutex == acpi_gbl_global_lock_mutex) { 417 if (obj_desc == acpi_gbl_global_lock_mutex) {
361 418
362 /* Ignore errors */ 419 /* Ignore errors */
363 420
@@ -369,6 +426,7 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread)
369 /* Mark mutex unowned */ 426 /* Mark mutex unowned */
370 427
371 obj_desc->mutex.owner_thread = NULL; 428 obj_desc->mutex.owner_thread = NULL;
429 obj_desc->mutex.thread_id = 0;
372 430
373 /* Update Thread sync_level (Last mutex is the important one) */ 431 /* Update Thread sync_level (Last mutex is the important one) */
374 432
diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c
index 6b0aeccbb69b..c0837af0acb1 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)
240 * PARAMETERS: field_flags - Flags with Lock rule: 240 * PARAMETERS: field_flags - Flags with Lock rule:
241 * always_lock or never_lock 241 * always_lock or never_lock
242 * 242 *
243 * RETURN: TRUE/FALSE indicating whether the lock was actually acquired 243 * RETURN: None
244 * 244 *
245 * DESCRIPTION: Obtain the global lock and keep track of this fact via two 245 * DESCRIPTION: Obtain the ACPI hardware Global Lock, only if the field
246 * methods. A global variable keeps the state of the lock, and 246 * flags specifiy that it is to be obtained before field access.
247 * the state is returned to the caller.
248 * 247 *
249 ******************************************************************************/ 248 ******************************************************************************/
250 249
251u8 acpi_ex_acquire_global_lock(u32 field_flags) 250void acpi_ex_acquire_global_lock(u32 field_flags)
252{ 251{
253 u8 locked = FALSE;
254 acpi_status status; 252 acpi_status status;
255 253
256 ACPI_FUNCTION_TRACE(ex_acquire_global_lock); 254 ACPI_FUNCTION_TRACE(ex_acquire_global_lock);
257 255
258 /* Only attempt lock if the always_lock bit is set */ 256 /* Only use the lock if the always_lock bit is set */
257
258 if (!(field_flags & AML_FIELD_LOCK_RULE_MASK)) {
259 return_VOID;
260 }
259 261
260 if (field_flags & AML_FIELD_LOCK_RULE_MASK) { 262 /* Attempt to get the global lock, wait forever */
261 263
262 /* We should attempt to get the lock, wait forever */ 264 status = acpi_ex_acquire_mutex_object(ACPI_WAIT_FOREVER,
265 acpi_gbl_global_lock_mutex,
266 acpi_os_get_thread_id());
263 267
264 status = acpi_ev_acquire_global_lock(ACPI_WAIT_FOREVER); 268 if (ACPI_FAILURE(status)) {
265 if (ACPI_SUCCESS(status)) { 269 ACPI_EXCEPTION((AE_INFO, status,
266 locked = TRUE; 270 "Could not acquire Global Lock"));
267 } else {
268 ACPI_EXCEPTION((AE_INFO, status,
269 "Could not acquire Global Lock"));
270 }
271 } 271 }
272 272
273 return_UINT8(locked); 273 return_VOID;
274} 274}
275 275
276/******************************************************************************* 276/*******************************************************************************
277 * 277 *
278 * FUNCTION: acpi_ex_release_global_lock 278 * FUNCTION: acpi_ex_release_global_lock
279 * 279 *
280 * PARAMETERS: locked_by_me - Return value from corresponding call to 280 * PARAMETERS: None
281 * acquire_global_lock.
282 * 281 *
283 * RETURN: None 282 * RETURN: None
284 * 283 *
285 * DESCRIPTION: Release the global lock if it is locked. 284 * DESCRIPTION: Release the ACPI hardware Global Lock
286 * 285 *
287 ******************************************************************************/ 286 ******************************************************************************/
288 287
289void acpi_ex_release_global_lock(u8 locked_by_me) 288void acpi_ex_release_global_lock(void)
290{ 289{
291 acpi_status status; 290 acpi_status status;
292 291
293 ACPI_FUNCTION_TRACE(ex_release_global_lock); 292 ACPI_FUNCTION_TRACE(ex_release_global_lock);
294 293
295 /* Only attempt unlock if the caller locked it */ 294 /* Release the global lock */
296
297 if (locked_by_me) {
298 295
299 /* OK, now release the lock */ 296 status = acpi_ex_release_mutex_object(acpi_gbl_global_lock_mutex);
300 297 if (ACPI_FAILURE(status)) {
301 status = acpi_ev_release_global_lock();
302 if (ACPI_FAILURE(status)) {
303 298
304 /* Report the error, but there isn't much else we can do */ 299 /* Report the error, but there isn't much else we can do */
305 300
306 ACPI_EXCEPTION((AE_INFO, status, 301 ACPI_EXCEPTION((AE_INFO, status,
307 "Could not release ACPI Global Lock")); 302 "Could not release Global Lock"));
308 }
309 } 303 }
310 304
311 return_VOID; 305 return_VOID;
diff --git a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c
index 57faf598bad8..32a01673cae8 100644
--- a/drivers/acpi/namespace/nsaccess.c
+++ b/drivers/acpi/namespace/nsaccess.c
@@ -208,8 +208,7 @@ acpi_status acpi_ns_root_initialize(void)
208 /* Special case for ACPI Global Lock */ 208 /* Special case for ACPI Global Lock */
209 209
210 if (ACPI_STRCMP(init_val->name, "_GL_") == 0) { 210 if (ACPI_STRCMP(init_val->name, "_GL_") == 0) {
211 acpi_gbl_global_lock_mutex = 211 acpi_gbl_global_lock_mutex = obj_desc;
212 obj_desc->mutex.os_mutex;
213 212
214 /* Create additional counting semaphore for global lock */ 213 /* Create additional counting semaphore for global lock */
215 214
diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c
index f777cebdc46d..dcb34f805714 100644
--- a/drivers/acpi/utilities/utdelete.c
+++ b/drivers/acpi/utilities/utdelete.c
@@ -158,7 +158,7 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object)
158 "***** Mutex %p, OS Mutex %p\n", 158 "***** Mutex %p, OS Mutex %p\n",
159 object, object->mutex.os_mutex)); 159 object, object->mutex.os_mutex));
160 160
161 if (object->mutex.os_mutex == acpi_gbl_global_lock_mutex) { 161 if (object == acpi_gbl_global_lock_mutex) {
162 162
163 /* Global Lock has extra semaphore */ 163 /* Global Lock has extra semaphore */
164 164
diff --git a/include/acpi/acglobal.h b/include/acpi/acglobal.h
index 47a1fd8f2d8a..e91008eaef2d 100644
--- a/include/acpi/acglobal.h
+++ b/include/acpi/acglobal.h
@@ -170,10 +170,14 @@ ACPI_EXTERN u8 acpi_gbl_integer_nybble_width;
170ACPI_EXTERN struct acpi_mutex_info acpi_gbl_mutex_info[ACPI_NUM_MUTEX]; 170ACPI_EXTERN struct acpi_mutex_info acpi_gbl_mutex_info[ACPI_NUM_MUTEX];
171 171
172/* 172/*
173 * Global lock semaphore works in conjunction with the actual HW global lock 173 * Global lock mutex is an actual AML mutex object
174 * Global lock semaphore works in conjunction with the HW global lock
174 */ 175 */
175ACPI_EXTERN acpi_mutex acpi_gbl_global_lock_mutex; 176ACPI_EXTERN union acpi_operand_object *acpi_gbl_global_lock_mutex;
176ACPI_EXTERN acpi_semaphore acpi_gbl_global_lock_semaphore; 177ACPI_EXTERN acpi_semaphore acpi_gbl_global_lock_semaphore;
178ACPI_EXTERN u16 acpi_gbl_global_lock_handle;
179ACPI_EXTERN u8 acpi_gbl_global_lock_acquired;
180ACPI_EXTERN u8 acpi_gbl_global_lock_present;
177 181
178/* 182/*
179 * Spinlocks are used for interfaces that can be possibly called at 183 * Spinlocks are used for interfaces that can be possibly called at
@@ -215,22 +219,22 @@ ACPI_EXTERN acpi_exception_handler acpi_gbl_exception_handler;
215ACPI_EXTERN acpi_init_handler acpi_gbl_init_handler; 219ACPI_EXTERN acpi_init_handler acpi_gbl_init_handler;
216ACPI_EXTERN struct acpi_walk_state *acpi_gbl_breakpoint_walk; 220ACPI_EXTERN struct acpi_walk_state *acpi_gbl_breakpoint_walk;
217 221
222/* Owner ID support */
223
224ACPI_EXTERN u32 acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS];
225ACPI_EXTERN u8 acpi_gbl_last_owner_id_index;
226ACPI_EXTERN u8 acpi_gbl_next_owner_id_offset;
227
218/* Misc */ 228/* Misc */
219 229
220ACPI_EXTERN u32 acpi_gbl_original_mode; 230ACPI_EXTERN u32 acpi_gbl_original_mode;
221ACPI_EXTERN u32 acpi_gbl_rsdp_original_location; 231ACPI_EXTERN u32 acpi_gbl_rsdp_original_location;
222ACPI_EXTERN u32 acpi_gbl_ns_lookup_count; 232ACPI_EXTERN u32 acpi_gbl_ns_lookup_count;
223ACPI_EXTERN u32 acpi_gbl_ps_find_count; 233ACPI_EXTERN u32 acpi_gbl_ps_find_count;
224ACPI_EXTERN u32 acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS];
225ACPI_EXTERN u16 acpi_gbl_pm1_enable_register_save; 234ACPI_EXTERN u16 acpi_gbl_pm1_enable_register_save;
226ACPI_EXTERN u16 acpi_gbl_global_lock_handle;
227ACPI_EXTERN u8 acpi_gbl_last_owner_id_index;
228ACPI_EXTERN u8 acpi_gbl_next_owner_id_offset;
229ACPI_EXTERN u8 acpi_gbl_debugger_configuration; 235ACPI_EXTERN u8 acpi_gbl_debugger_configuration;
230ACPI_EXTERN u8 acpi_gbl_global_lock_acquired;
231ACPI_EXTERN u8 acpi_gbl_step_to_next_call; 236ACPI_EXTERN u8 acpi_gbl_step_to_next_call;
232ACPI_EXTERN u8 acpi_gbl_acpi_hardware_present; 237ACPI_EXTERN u8 acpi_gbl_acpi_hardware_present;
233ACPI_EXTERN u8 acpi_gbl_global_lock_present;
234ACPI_EXTERN u8 acpi_gbl_events_initialized; 238ACPI_EXTERN u8 acpi_gbl_events_initialized;
235ACPI_EXTERN u8 acpi_gbl_system_awake_and_running; 239ACPI_EXTERN u8 acpi_gbl_system_awake_and_running;
236 240
diff --git a/include/acpi/acinterp.h b/include/acpi/acinterp.h
index ce7c9d653910..23863886e808 100644
--- a/include/acpi/acinterp.h
+++ b/include/acpi/acinterp.h
@@ -248,9 +248,16 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc,
248 struct acpi_walk_state *walk_state); 248 struct acpi_walk_state *walk_state);
249 249
250acpi_status 250acpi_status
251acpi_ex_acquire_mutex_object(u16 timeout,
252 union acpi_operand_object *obj_desc,
253 acpi_thread_id thread_id);
254
255acpi_status
251acpi_ex_release_mutex(union acpi_operand_object *obj_desc, 256acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
252 struct acpi_walk_state *walk_state); 257 struct acpi_walk_state *walk_state);
253 258
259acpi_status acpi_ex_release_mutex_object(union acpi_operand_object *obj_desc);
260
254void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread); 261void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread);
255 262
256void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc); 263void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc);
@@ -455,9 +462,9 @@ void acpi_ex_relinquish_interpreter(void);
455 462
456void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc); 463void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc);
457 464
458u8 acpi_ex_acquire_global_lock(u32 rule); 465void acpi_ex_acquire_global_lock(u32 rule);
459 466
460void acpi_ex_release_global_lock(u8 locked); 467void acpi_ex_release_global_lock(void);
461 468
462void acpi_ex_eisa_id_to_string(u32 numeric_id, char *out_string); 469void acpi_ex_eisa_id_to_string(u32 numeric_id, char *out_string);
463 470
diff --git a/include/acpi/acobject.h b/include/acpi/acobject.h
index 7e1211a8b8fa..2461bb9ab3e9 100644
--- a/include/acpi/acobject.h
+++ b/include/acpi/acobject.h
@@ -155,8 +155,9 @@ struct acpi_object_event {
155struct acpi_object_mutex { 155struct acpi_object_mutex {
156 ACPI_OBJECT_COMMON_HEADER u8 sync_level; /* 0-15, specified in Mutex() call */ 156 ACPI_OBJECT_COMMON_HEADER u8 sync_level; /* 0-15, specified in Mutex() call */
157 u16 acquisition_depth; /* Allow multiple Acquires, same thread */ 157 u16 acquisition_depth; /* Allow multiple Acquires, same thread */
158 struct acpi_thread_state *owner_thread; /* Current owner of the mutex */
159 acpi_mutex os_mutex; /* Actual OS synchronization object */ 158 acpi_mutex os_mutex; /* Actual OS synchronization object */
159 acpi_thread_id thread_id; /* Current owner of the mutex */
160 struct acpi_thread_state *owner_thread; /* Current owner of the mutex */
160 union acpi_operand_object *prev; /* Link for list of acquired mutexes */ 161 union acpi_operand_object *prev; /* Link for list of acquired mutexes */
161 union acpi_operand_object *next; /* Link for list of acquired mutexes */ 162 union acpi_operand_object *next; /* Link for list of acquired mutexes */
162 struct acpi_namespace_node *node; /* Containing namespace node */ 163 struct acpi_namespace_node *node; /* Containing namespace node */