aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/executer
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 /drivers/acpi/executer
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>
Diffstat (limited to 'drivers/acpi/executer')
-rw-r--r--drivers/acpi/executer/exfield.c24
-rw-r--r--drivers/acpi/executer/exmutex.c194
-rw-r--r--drivers/acpi/executer/exutils.c58
3 files changed, 160 insertions, 116 deletions
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;