aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/events
diff options
context:
space:
mode:
authorBob Moore <robert.moore@intel.com>2007-02-02 11:48:18 -0500
committerLen Brown <len.brown@intel.com>2007-02-02 21:14:20 -0500
commitc81da66608d65dab04730582dfdfcdcab779e2fe (patch)
treee1d2936a457d3ac2b359b4fc676bedfd341fee86 /drivers/acpi/events
parent8f9337c88335846b01801b1047a4caf10527a320 (diff)
ACPICA: Delete recursive feature of ACPI Global Lock
Completed a new design and implementation for the ACPI Global Lock support. On the OS side, the global lock is now treated as a standard AML mutex. Previously, multiple OS threads could acquire the global lock simultaneously, but this could cause the BIOS to be starved by the lock in cases such as the Embedded Controller driver, where there is a tight coupling between the OS and the BIOS. Signed-off-by: Alexey Starikovskiy <alexey.y.starikovskiy@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/events')
-rw-r--r--drivers/acpi/events/evmisc.c113
1 files changed, 59 insertions, 54 deletions
diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c
index bf63edc6608d..f82b81cc1838 100644
--- a/drivers/acpi/events/evmisc.c
+++ b/drivers/acpi/events/evmisc.c
@@ -298,19 +298,13 @@ static void ACPI_SYSTEM_XFACE acpi_ev_global_lock_thread(void *context)
298{ 298{
299 acpi_status status; 299 acpi_status status;
300 300
301 /* Signal threads that are waiting for the lock */ 301 /* Signal the thread that is waiting for the lock */
302 302
303 if (acpi_gbl_global_lock_thread_count) { 303 /* Send a unit to the semaphore */
304 304
305 /* Send sufficient units to the semaphore */ 305 status = acpi_os_signal_semaphore(acpi_gbl_global_lock_semaphore, 1);
306 306 if (ACPI_FAILURE(status)) {
307 status = 307 ACPI_ERROR((AE_INFO, "Could not signal Global Lock semaphore"));
308 acpi_os_signal_semaphore(acpi_gbl_global_lock_semaphore,
309 acpi_gbl_global_lock_thread_count);
310 if (ACPI_FAILURE(status)) {
311 ACPI_ERROR((AE_INFO,
312 "Could not signal Global Lock semaphore"));
313 }
314 } 308 }
315} 309}
316 310
@@ -333,7 +327,8 @@ static u32 acpi_ev_global_lock_handler(void *context)
333 u8 acquired = FALSE; 327 u8 acquired = FALSE;
334 328
335 /* 329 /*
336 * Attempt to get the lock 330 * Attempt to get the lock.
331 *
337 * If we don't get it now, it will be marked pending and we will 332 * If we don't get it now, it will be marked pending and we will
338 * take another interrupt when it becomes free. 333 * take another interrupt when it becomes free.
339 */ 334 */
@@ -341,6 +336,7 @@ static u32 acpi_ev_global_lock_handler(void *context)
341 if (acquired) { 336 if (acquired) {
342 337
343 /* Got the lock, now wake all threads waiting for it */ 338 /* Got the lock, now wake all threads waiting for it */
339
344 acpi_gbl_global_lock_acquired = TRUE; 340 acpi_gbl_global_lock_acquired = TRUE;
345 acpi_ev_global_lock_thread(context); 341 acpi_ev_global_lock_thread(context);
346 } 342 }
@@ -399,6 +395,16 @@ acpi_status acpi_ev_init_global_lock_handler(void)
399 * 395 *
400 * DESCRIPTION: Attempt to gain ownership of the Global Lock. 396 * DESCRIPTION: Attempt to gain ownership of the Global Lock.
401 * 397 *
398 * MUTEX: Interpreter must be locked
399 *
400 * Note: The original implementation allowed multiple threads to "acquire" the
401 * Global Lock, and the OS would hold the lock until the last thread had
402 * released it. However, this could potentially starve the BIOS out of the
403 * lock, especially in the case where there is a tight handshake between the
404 * Embedded Controller driver and the BIOS. Therefore, this implementation
405 * allows only one thread to acquire the HW Global Lock at a time, and makes
406 * the global lock appear as a standard mutex on the OS side.
407 *
402 *****************************************************************************/ 408 *****************************************************************************/
403 409
404acpi_status acpi_ev_acquire_global_lock(u16 timeout) 410acpi_status acpi_ev_acquire_global_lock(u16 timeout)
@@ -408,27 +414,25 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout)
408 414
409 ACPI_FUNCTION_TRACE(ev_acquire_global_lock); 415 ACPI_FUNCTION_TRACE(ev_acquire_global_lock);
410 416
411#ifndef ACPI_APPLICATION 417 /*
412 /* Make sure that we actually have a global lock */ 418 * Only one thread can acquire the GL at a time, the global_lock_mutex
413 419 * enforces this. This interface releases the interpreter if we must wait.
414 if (!acpi_gbl_global_lock_present) { 420 */
415 return_ACPI_STATUS(AE_NO_GLOBAL_LOCK); 421 status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, timeout);
422 if (ACPI_FAILURE(status)) {
423 return_ACPI_STATUS(status);
416 } 424 }
417#endif
418
419 /* One more thread wants the global lock */
420
421 acpi_gbl_global_lock_thread_count++;
422 425
423 /* 426 /*
424 * If we (OS side vs. BIOS side) have the hardware lock already, 427 * Make sure that a global lock actually exists. If not, just treat
425 * we are done 428 * the lock as a standard mutex.
426 */ 429 */
427 if (acpi_gbl_global_lock_acquired) { 430 if (!acpi_gbl_global_lock_present) {
431 acpi_gbl_global_lock_acquired = TRUE;
428 return_ACPI_STATUS(AE_OK); 432 return_ACPI_STATUS(AE_OK);
429 } 433 }
430 434
431 /* We must acquire the actual hardware lock */ 435 /* Attempt to acquire the actual hardware lock */
432 436
433 ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_common_fACS.global_lock, acquired); 437 ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_common_fACS.global_lock, acquired);
434 if (acquired) { 438 if (acquired) {
@@ -436,25 +440,24 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout)
436 /* We got the lock */ 440 /* We got the lock */
437 441
438 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 442 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
439 "Acquired the HW Global Lock\n")); 443 "Acquired hardware Global Lock\n"));
440 444
441 acpi_gbl_global_lock_acquired = TRUE; 445 acpi_gbl_global_lock_acquired = TRUE;
442 return_ACPI_STATUS(AE_OK); 446 return_ACPI_STATUS(AE_OK);
443 } 447 }
444 448
445 /* 449 /*
446 * Did not get the lock. The pending bit was set above, and we must now 450 * Did not get the lock. The pending bit was set above, and we must now
447 * wait until we get the global lock released interrupt. 451 * wait until we get the global lock released interrupt.
448 */ 452 */
449 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Waiting for the HW Global Lock\n")); 453 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Waiting for hardware Global Lock\n"));
450 454
451 /* 455 /*
452 * Acquire the global lock semaphore first. 456 * Wait for handshake with the global lock interrupt handler.
453 * Since this wait will block, we must release the interpreter 457 * This interface releases the interpreter if we must wait.
454 */ 458 */
455 status = 459 status = acpi_ex_system_wait_semaphore(acpi_gbl_global_lock_semaphore,
456 acpi_ex_system_wait_semaphore(acpi_gbl_global_lock_semaphore, 460 ACPI_WAIT_FOREVER);
457 timeout);
458 return_ACPI_STATUS(status); 461 return_ACPI_STATUS(status);
459} 462}
460 463
@@ -477,38 +480,40 @@ acpi_status acpi_ev_release_global_lock(void)
477 480
478 ACPI_FUNCTION_TRACE(ev_release_global_lock); 481 ACPI_FUNCTION_TRACE(ev_release_global_lock);
479 482
480 if (!acpi_gbl_global_lock_thread_count) { 483 /* Lock must be acquired */
484
485 if (!acpi_gbl_global_lock_acquired) {
481 ACPI_WARNING((AE_INFO, 486 ACPI_WARNING((AE_INFO,
482 "Cannot release HW Global Lock, it has not been acquired")); 487 "Cannot release the ACPI Global Lock, it has not been acquired"));
483 return_ACPI_STATUS(AE_NOT_ACQUIRED); 488 return_ACPI_STATUS(AE_NOT_ACQUIRED);
484 } 489 }
485 490
486 /* One fewer thread has the global lock */ 491 if (acpi_gbl_global_lock_present) {
487 492
488 acpi_gbl_global_lock_thread_count--; 493 /* Allow any thread to release the lock */
489 if (acpi_gbl_global_lock_thread_count) {
490 494
491 /* There are still some threads holding the lock, cannot release */ 495 ACPI_RELEASE_GLOBAL_LOCK(acpi_gbl_common_fACS.global_lock,
496 pending);
492 497
493 return_ACPI_STATUS(AE_OK); 498 /*
499 * If the pending bit was set, we must write GBL_RLS to the control
500 * register
501 */
502 if (pending) {
503 status =
504 acpi_set_register(ACPI_BITREG_GLOBAL_LOCK_RELEASE,
505 1, ACPI_MTX_LOCK);
506 }
507
508 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
509 "Released hardware Global Lock\n"));
494 } 510 }
495 511
496 /*
497 * No more threads holding lock, we can do the actual hardware
498 * release
499 */
500 ACPI_RELEASE_GLOBAL_LOCK(acpi_gbl_common_fACS.global_lock, pending);
501 acpi_gbl_global_lock_acquired = FALSE; 512 acpi_gbl_global_lock_acquired = FALSE;
502 513
503 /* 514 /* Release the local GL mutex */
504 * If the pending bit was set, we must write GBL_RLS to the control
505 * register
506 */
507 if (pending) {
508 status = acpi_set_register(ACPI_BITREG_GLOBAL_LOCK_RELEASE,
509 1, ACPI_MTX_LOCK);
510 }
511 515
516 acpi_os_release_mutex(acpi_gbl_global_lock_mutex);
512 return_ACPI_STATUS(status); 517 return_ACPI_STATUS(status);
513} 518}
514 519