diff options
-rw-r--r-- | drivers/acpi/dispatcher/dsmethod.c | 12 | ||||
-rw-r--r-- | drivers/acpi/events/evmisc.c | 11 | ||||
-rw-r--r-- | drivers/acpi/events/evxface.c | 26 | ||||
-rw-r--r-- | drivers/acpi/executer/exfield.c | 24 | ||||
-rw-r--r-- | drivers/acpi/executer/exmutex.c | 194 | ||||
-rw-r--r-- | drivers/acpi/executer/exutils.c | 58 | ||||
-rw-r--r-- | drivers/acpi/namespace/nsaccess.c | 3 | ||||
-rw-r--r-- | drivers/acpi/utilities/utdelete.c | 2 | ||||
-rw-r--r-- | include/acpi/acglobal.h | 20 | ||||
-rw-r--r-- | include/acpi/acinterp.h | 11 | ||||
-rw-r--r-- | include/acpi/acobject.h | 3 |
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 | ******************************************************************************/ |
762 | acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle) | 768 | acpi_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 | |||
141 | acpi_status | ||
142 | acpi_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)) { | 265 | acpi_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 | ||
251 | u8 acpi_ex_acquire_global_lock(u32 field_flags) | 250 | void 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 | ||
289 | void acpi_ex_release_global_lock(u8 locked_by_me) | 288 | void 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; | |||
170 | ACPI_EXTERN struct acpi_mutex_info acpi_gbl_mutex_info[ACPI_NUM_MUTEX]; | 170 | ACPI_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 | */ |
175 | ACPI_EXTERN acpi_mutex acpi_gbl_global_lock_mutex; | 176 | ACPI_EXTERN union acpi_operand_object *acpi_gbl_global_lock_mutex; |
176 | ACPI_EXTERN acpi_semaphore acpi_gbl_global_lock_semaphore; | 177 | ACPI_EXTERN acpi_semaphore acpi_gbl_global_lock_semaphore; |
178 | ACPI_EXTERN u16 acpi_gbl_global_lock_handle; | ||
179 | ACPI_EXTERN u8 acpi_gbl_global_lock_acquired; | ||
180 | ACPI_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; | |||
215 | ACPI_EXTERN acpi_init_handler acpi_gbl_init_handler; | 219 | ACPI_EXTERN acpi_init_handler acpi_gbl_init_handler; |
216 | ACPI_EXTERN struct acpi_walk_state *acpi_gbl_breakpoint_walk; | 220 | ACPI_EXTERN struct acpi_walk_state *acpi_gbl_breakpoint_walk; |
217 | 221 | ||
222 | /* Owner ID support */ | ||
223 | |||
224 | ACPI_EXTERN u32 acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS]; | ||
225 | ACPI_EXTERN u8 acpi_gbl_last_owner_id_index; | ||
226 | ACPI_EXTERN u8 acpi_gbl_next_owner_id_offset; | ||
227 | |||
218 | /* Misc */ | 228 | /* Misc */ |
219 | 229 | ||
220 | ACPI_EXTERN u32 acpi_gbl_original_mode; | 230 | ACPI_EXTERN u32 acpi_gbl_original_mode; |
221 | ACPI_EXTERN u32 acpi_gbl_rsdp_original_location; | 231 | ACPI_EXTERN u32 acpi_gbl_rsdp_original_location; |
222 | ACPI_EXTERN u32 acpi_gbl_ns_lookup_count; | 232 | ACPI_EXTERN u32 acpi_gbl_ns_lookup_count; |
223 | ACPI_EXTERN u32 acpi_gbl_ps_find_count; | 233 | ACPI_EXTERN u32 acpi_gbl_ps_find_count; |
224 | ACPI_EXTERN u32 acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS]; | ||
225 | ACPI_EXTERN u16 acpi_gbl_pm1_enable_register_save; | 234 | ACPI_EXTERN u16 acpi_gbl_pm1_enable_register_save; |
226 | ACPI_EXTERN u16 acpi_gbl_global_lock_handle; | ||
227 | ACPI_EXTERN u8 acpi_gbl_last_owner_id_index; | ||
228 | ACPI_EXTERN u8 acpi_gbl_next_owner_id_offset; | ||
229 | ACPI_EXTERN u8 acpi_gbl_debugger_configuration; | 235 | ACPI_EXTERN u8 acpi_gbl_debugger_configuration; |
230 | ACPI_EXTERN u8 acpi_gbl_global_lock_acquired; | ||
231 | ACPI_EXTERN u8 acpi_gbl_step_to_next_call; | 236 | ACPI_EXTERN u8 acpi_gbl_step_to_next_call; |
232 | ACPI_EXTERN u8 acpi_gbl_acpi_hardware_present; | 237 | ACPI_EXTERN u8 acpi_gbl_acpi_hardware_present; |
233 | ACPI_EXTERN u8 acpi_gbl_global_lock_present; | ||
234 | ACPI_EXTERN u8 acpi_gbl_events_initialized; | 238 | ACPI_EXTERN u8 acpi_gbl_events_initialized; |
235 | ACPI_EXTERN u8 acpi_gbl_system_awake_and_running; | 239 | ACPI_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 | ||
250 | acpi_status | 250 | acpi_status |
251 | acpi_ex_acquire_mutex_object(u16 timeout, | ||
252 | union acpi_operand_object *obj_desc, | ||
253 | acpi_thread_id thread_id); | ||
254 | |||
255 | acpi_status | ||
251 | acpi_ex_release_mutex(union acpi_operand_object *obj_desc, | 256 | acpi_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 | ||
259 | acpi_status acpi_ex_release_mutex_object(union acpi_operand_object *obj_desc); | ||
260 | |||
254 | void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread); | 261 | void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread); |
255 | 262 | ||
256 | void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc); | 263 | void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc); |
@@ -455,9 +462,9 @@ void acpi_ex_relinquish_interpreter(void); | |||
455 | 462 | ||
456 | void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc); | 463 | void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc); |
457 | 464 | ||
458 | u8 acpi_ex_acquire_global_lock(u32 rule); | 465 | void acpi_ex_acquire_global_lock(u32 rule); |
459 | 466 | ||
460 | void acpi_ex_release_global_lock(u8 locked); | 467 | void acpi_ex_release_global_lock(void); |
461 | 468 | ||
462 | void acpi_ex_eisa_id_to_string(u32 numeric_id, char *out_string); | 469 | void 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 { | |||
155 | struct acpi_object_mutex { | 155 | struct 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 */ |