Merge branch 'acpica' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux...
[linux-3.10.git] / drivers / acpi / acpica / evmisc.c
index ccd230b7aba430f744bf3d6474219961fd115184..7dc80946f7bd3c0f10a09fb35b38d44f3f23d651 100644 (file)
@@ -284,41 +284,39 @@ static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context)
  * RETURN:      ACPI_INTERRUPT_HANDLED
  *
  * DESCRIPTION: Invoked directly from the SCI handler when a global lock
- *              release interrupt occurs. Attempt to acquire the global lock,
- *              if successful, signal the thread waiting for the lock.
+ *              release interrupt occurs.  If there's a thread waiting for
+ *              the global lock, signal it.
  *
  * NOTE: Assumes that the semaphore can be signaled from interrupt level. If
  * this is not possible for some reason, a separate thread will have to be
  * scheduled to do this.
  *
  ******************************************************************************/
+static u8 acpi_ev_global_lock_pending;
 
 static u32 acpi_ev_global_lock_handler(void *context)
 {
-       u8 acquired = FALSE;
+       acpi_status status;
+       acpi_cpu_flags flags;
 
-       /*
-        * Attempt to get the lock.
-        *
-        * If we don't get it now, it will be marked pending and we will
-        * take another interrupt when it becomes free.
-        */
-       ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_FACS, acquired);
-       if (acquired) {
+       flags = acpi_os_acquire_lock(acpi_ev_global_lock_pending_lock);
 
-               /* Got the lock, now wake all threads waiting for it */
+       if (!acpi_ev_global_lock_pending) {
+               goto out;
+       }
 
-               acpi_gbl_global_lock_acquired = TRUE;
-               /* Send a unit to the semaphore */
+       /* Send a unit to the semaphore */
 
-               if (ACPI_FAILURE
-                   (acpi_os_signal_semaphore
-                    (acpi_gbl_global_lock_semaphore, 1))) {
-                       ACPI_ERROR((AE_INFO,
-                                   "Could not signal Global Lock semaphore"));
-               }
+       status = acpi_os_signal_semaphore(acpi_gbl_global_lock_semaphore, 1);
+       if (ACPI_FAILURE(status)) {
+               ACPI_ERROR((AE_INFO, "Could not signal Global Lock semaphore"));
        }
 
+       acpi_ev_global_lock_pending = FALSE;
+
+ out:
+       acpi_os_release_lock(acpi_ev_global_lock_pending_lock, flags);
+
        return (ACPI_INTERRUPT_HANDLED);
 }
 
@@ -415,6 +413,7 @@ static int acpi_ev_global_lock_acquired;
 
 acpi_status acpi_ev_acquire_global_lock(u16 timeout)
 {
+       acpi_cpu_flags flags;
        acpi_status status = AE_OK;
        u8 acquired = FALSE;
 
@@ -467,32 +466,47 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout)
                return_ACPI_STATUS(AE_OK);
        }
 
-       /* Attempt to acquire the actual hardware lock */
+       flags = acpi_os_acquire_lock(acpi_ev_global_lock_pending_lock);
+
+       do {
+
+               /* Attempt to acquire the actual hardware lock */
+
+               ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_FACS, acquired);
+               if (acquired) {
+                       acpi_gbl_global_lock_acquired = TRUE;
+
+                       ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+                                         "Acquired hardware Global Lock\n"));
+                       break;
+               }
 
-       ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_FACS, acquired);
-       if (acquired) {
+               acpi_ev_global_lock_pending = TRUE;
 
-               /* We got the lock */
+               acpi_os_release_lock(acpi_ev_global_lock_pending_lock, flags);
 
+               /*
+                * Did not get the lock. The pending bit was set above, and we
+                * must wait until we get the global lock released interrupt.
+                */
                ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
-                                 "Acquired hardware Global Lock\n"));
+                                 "Waiting for hardware Global Lock\n"));
 
-               acpi_gbl_global_lock_acquired = TRUE;
-               return_ACPI_STATUS(AE_OK);
-       }
+               /*
+                * Wait for handshake with the global lock interrupt handler.
+                * This interface releases the interpreter if we must wait.
+                */
+               status = acpi_ex_system_wait_semaphore(
+                                               acpi_gbl_global_lock_semaphore,
+                                               ACPI_WAIT_FOREVER);
 
-       /*
-        * Did not get the lock. The pending bit was set above, and we must now
-        * wait until we get the global lock released interrupt.
-        */
-       ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Waiting for hardware Global Lock\n"));
+               flags = acpi_os_acquire_lock(acpi_ev_global_lock_pending_lock);
 
-       /*
-        * Wait for handshake with the global lock interrupt handler.
-        * This interface releases the interpreter if we must wait.
-        */
-       status = acpi_ex_system_wait_semaphore(acpi_gbl_global_lock_semaphore,
-                                              ACPI_WAIT_FOREVER);
+       } while (ACPI_SUCCESS(status));
+
+       acpi_ev_global_lock_pending = FALSE;
+
+       acpi_os_release_lock(acpi_ev_global_lock_pending_lock, flags);
 
        return_ACPI_STATUS(status);
 }