diff options
author | Alexey Starikovskiy <alexey.y.starikovskiy@linux.intel.com> | 2007-02-15 16:12:23 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2007-02-15 16:13:16 -0500 |
commit | c0d127b56937c3e72c2b1819161d2f6718eee877 (patch) | |
tree | 40ac0fd3a628685ce25d11d1b00360344279ec5b /drivers/acpi/executer | |
parent | 724339d76d9407cd1a8ad32a9c1fdf64840cc51b (diff) |
ACPICA: fix AML mutex re-entrancy
ACPI AML supports "serialized" methods which are protected
by an implicit mutex. The mutex is re-entrant for that AML thread
to allow recursion.
However, Linux implements notify() by creating a new AML thread.
So for systems where notify() re-enters a serialized method,
deadlock results.
The fix is to use the Linux thread_id as the key to allowing
re-entrancy, not the AML thread pointer.
http://bugzilla.kernel.org/show_bug.cgi?id=5534
Signed-off-by: Alexey Starikovskiy <alexey.y.starikovskiy@linux.intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/executer')
-rw-r--r-- | drivers/acpi/executer/exdump.c | 2 | ||||
-rw-r--r-- | drivers/acpi/executer/exmutex.c | 36 |
2 files changed, 17 insertions, 21 deletions
diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c index 68d283fd60e7..1a73c14df2c5 100644 --- a/drivers/acpi/executer/exdump.c +++ b/drivers/acpi/executer/exdump.c | |||
@@ -134,7 +134,7 @@ static struct acpi_exdump_info acpi_ex_dump_method[8] = { | |||
134 | static struct acpi_exdump_info acpi_ex_dump_mutex[5] = { | 134 | static struct acpi_exdump_info acpi_ex_dump_mutex[5] = { |
135 | {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_mutex), NULL}, | 135 | {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_mutex), NULL}, |
136 | {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(mutex.sync_level), "Sync Level"}, | 136 | {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(mutex.sync_level), "Sync Level"}, |
137 | {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.owner_thread), "Owner Thread"}, | 137 | {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.owner_thread_id), "Owner Thread"}, |
138 | {ACPI_EXD_UINT16, ACPI_EXD_OFFSET(mutex.acquisition_depth), | 138 | {ACPI_EXD_UINT16, ACPI_EXD_OFFSET(mutex.acquisition_depth), |
139 | "Acquire Depth"}, | 139 | "Acquire Depth"}, |
140 | {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.os_mutex), "OsMutex"} | 140 | {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.os_mutex), "OsMutex"} |
diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c index 5101bad5baf8..4eb883bda6ae 100644 --- a/drivers/acpi/executer/exmutex.c +++ b/drivers/acpi/executer/exmutex.c | |||
@@ -66,10 +66,9 @@ acpi_ex_link_mutex(union acpi_operand_object *obj_desc, | |||
66 | * | 66 | * |
67 | ******************************************************************************/ | 67 | ******************************************************************************/ |
68 | 68 | ||
69 | void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc) | 69 | void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc, |
70 | struct acpi_thread_state *thread) | ||
70 | { | 71 | { |
71 | struct acpi_thread_state *thread = obj_desc->mutex.owner_thread; | ||
72 | |||
73 | if (!thread) { | 72 | if (!thread) { |
74 | return; | 73 | return; |
75 | } | 74 | } |
@@ -174,16 +173,13 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, | |||
174 | 173 | ||
175 | /* Support for multiple acquires by the owning thread */ | 174 | /* Support for multiple acquires by the owning thread */ |
176 | 175 | ||
177 | if (obj_desc->mutex.owner_thread) { | 176 | if (obj_desc->mutex.owner_thread_id == acpi_os_get_thread_id()) { |
178 | if (obj_desc->mutex.owner_thread->thread_id == | 177 | /* |
179 | walk_state->thread->thread_id) { | 178 | * The mutex is already owned by this thread, just increment the |
180 | /* | 179 | * acquisition depth |
181 | * The mutex is already owned by this thread, just increment the | 180 | */ |
182 | * acquisition depth | 181 | obj_desc->mutex.acquisition_depth++; |
183 | */ | 182 | return_ACPI_STATUS(AE_OK); |
184 | obj_desc->mutex.acquisition_depth++; | ||
185 | return_ACPI_STATUS(AE_OK); | ||
186 | } | ||
187 | } | 183 | } |
188 | 184 | ||
189 | /* Acquire the mutex, wait if necessary. Special case for Global Lock */ | 185 | /* Acquire the mutex, wait if necessary. Special case for Global Lock */ |
@@ -206,7 +202,7 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, | |||
206 | 202 | ||
207 | /* Have the mutex: update mutex and walk info and save the sync_level */ | 203 | /* Have the mutex: update mutex and walk info and save the sync_level */ |
208 | 204 | ||
209 | obj_desc->mutex.owner_thread = walk_state->thread; | 205 | obj_desc->mutex.owner_thread_id = acpi_os_get_thread_id(); |
210 | obj_desc->mutex.acquisition_depth = 1; | 206 | obj_desc->mutex.acquisition_depth = 1; |
211 | obj_desc->mutex.original_sync_level = | 207 | obj_desc->mutex.original_sync_level = |
212 | walk_state->thread->current_sync_level; | 208 | walk_state->thread->current_sync_level; |
@@ -246,7 +242,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, | |||
246 | 242 | ||
247 | /* The mutex must have been previously acquired in order to release it */ | 243 | /* The mutex must have been previously acquired in order to release it */ |
248 | 244 | ||
249 | if (!obj_desc->mutex.owner_thread) { | 245 | if (!obj_desc->mutex.owner_thread_id) { |
250 | ACPI_ERROR((AE_INFO, | 246 | ACPI_ERROR((AE_INFO, |
251 | "Cannot release Mutex [%4.4s], not acquired", | 247 | "Cannot release Mutex [%4.4s], not acquired", |
252 | acpi_ut_get_node_name(obj_desc->mutex.node))); | 248 | acpi_ut_get_node_name(obj_desc->mutex.node))); |
@@ -266,14 +262,14 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, | |||
266 | * The Mutex is owned, but this thread must be the owner. | 262 | * The Mutex is owned, but this thread must be the owner. |
267 | * Special case for Global Lock, any thread can release | 263 | * Special case for Global Lock, any thread can release |
268 | */ | 264 | */ |
269 | if ((obj_desc->mutex.owner_thread->thread_id != | 265 | if ((obj_desc->mutex.owner_thread_id != |
270 | walk_state->thread->thread_id) | 266 | walk_state->thread->thread_id) |
271 | && (obj_desc->mutex.os_mutex != acpi_gbl_global_lock_mutex)) { | 267 | && (obj_desc->mutex.os_mutex != acpi_gbl_global_lock_mutex)) { |
272 | ACPI_ERROR((AE_INFO, | 268 | ACPI_ERROR((AE_INFO, |
273 | "Thread %lX cannot release Mutex [%4.4s] acquired by thread %lX", | 269 | "Thread %lX cannot release Mutex [%4.4s] acquired by thread %lX", |
274 | (unsigned long)walk_state->thread->thread_id, | 270 | (unsigned long)walk_state->thread->thread_id, |
275 | acpi_ut_get_node_name(obj_desc->mutex.node), | 271 | acpi_ut_get_node_name(obj_desc->mutex.node), |
276 | (unsigned long)obj_desc->mutex.owner_thread->thread_id)); | 272 | (unsigned long)obj_desc->mutex.owner_thread_id)); |
277 | return_ACPI_STATUS(AE_AML_NOT_OWNER); | 273 | return_ACPI_STATUS(AE_AML_NOT_OWNER); |
278 | } | 274 | } |
279 | 275 | ||
@@ -300,7 +296,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, | |||
300 | 296 | ||
301 | /* Unlink the mutex from the owner's list */ | 297 | /* Unlink the mutex from the owner's list */ |
302 | 298 | ||
303 | acpi_ex_unlink_mutex(obj_desc); | 299 | acpi_ex_unlink_mutex(obj_desc, walk_state->thread); |
304 | 300 | ||
305 | /* Release the mutex, special case for Global Lock */ | 301 | /* Release the mutex, special case for Global Lock */ |
306 | 302 | ||
@@ -312,7 +308,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, | |||
312 | 308 | ||
313 | /* Update the mutex and restore sync_level */ | 309 | /* Update the mutex and restore sync_level */ |
314 | 310 | ||
315 | obj_desc->mutex.owner_thread = NULL; | 311 | obj_desc->mutex.owner_thread_id = ACPI_MUTEX_NOT_ACQUIRED; |
316 | walk_state->thread->current_sync_level = | 312 | walk_state->thread->current_sync_level = |
317 | obj_desc->mutex.original_sync_level; | 313 | obj_desc->mutex.original_sync_level; |
318 | 314 | ||
@@ -367,7 +363,7 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread) | |||
367 | 363 | ||
368 | /* Mark mutex unowned */ | 364 | /* Mark mutex unowned */ |
369 | 365 | ||
370 | obj_desc->mutex.owner_thread = NULL; | 366 | obj_desc->mutex.owner_thread_id = ACPI_MUTEX_NOT_ACQUIRED; |
371 | 367 | ||
372 | /* Update Thread sync_level (Last mutex is the important one) */ | 368 | /* Update Thread sync_level (Last mutex is the important one) */ |
373 | 369 | ||