]> err.no Git - linux-2.6/blobdiff - drivers/acpi/events/evmisc.c
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
[linux-2.6] / drivers / acpi / events / evmisc.c
index 21449f36b5f8d8d751228a57924c6db05b790238..21cb749d0c75567534ebee05c78551bb289f1972 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2006, R. Byron Moore
+ * Copyright (C) 2000 - 2007, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -73,6 +73,8 @@ static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context);
 
 static u32 acpi_ev_global_lock_handler(void *context);
 
+static acpi_status acpi_ev_remove_global_lock_handler(void);
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ev_is_notify_object
@@ -318,8 +320,9 @@ static u32 acpi_ev_global_lock_handler(void *context)
                acpi_gbl_global_lock_acquired = TRUE;
                /* Send a unit to the semaphore */
 
-               if (ACPI_FAILURE(acpi_os_signal_semaphore(
-                       acpi_gbl_global_lock_semaphore, 1))) {
+               if (ACPI_FAILURE
+                   (acpi_os_signal_semaphore
+                    (acpi_gbl_global_lock_semaphore, 1))) {
                        ACPI_ERROR((AE_INFO,
                                    "Could not signal Global Lock semaphore"));
                }
@@ -347,8 +350,8 @@ acpi_status acpi_ev_init_global_lock_handler(void)
        ACPI_FUNCTION_TRACE(ev_init_global_lock_handler);
 
        status =
-           acpi_get_table(ACPI_SIG_FACS, 0,
-                          (struct acpi_table_header **)&facs);
+           acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS,
+                                   (struct acpi_table_header **)&facs);
        if (ACPI_FAILURE(status)) {
                return_ACPI_STATUS(status);
        }
@@ -376,6 +379,31 @@ acpi_status acpi_ev_init_global_lock_handler(void)
        return_ACPI_STATUS(status);
 }
 
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ev_remove_global_lock_handler
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Remove the handler for the Global Lock
+ *
+ ******************************************************************************/
+
+static acpi_status acpi_ev_remove_global_lock_handler(void)
+{
+       acpi_status status;
+
+       ACPI_FUNCTION_TRACE(ev_remove_global_lock_handler);
+
+       acpi_gbl_global_lock_present = FALSE;
+       status = acpi_remove_fixed_event_handler(ACPI_EVENT_GLOBAL,
+                                                acpi_ev_global_lock_handler);
+
+       return_ACPI_STATUS(status);
+}
+
 /******************************************************************************
  *
  * FUNCTION:    acpi_ev_acquire_global_lock
@@ -397,6 +425,8 @@ acpi_status acpi_ev_init_global_lock_handler(void)
  * the global lock appear as a standard mutex on the OS side.
  *
  *****************************************************************************/
+static acpi_thread_id acpi_ev_global_lock_thread_id;
+static int acpi_ev_global_lock_acquired;
 
 acpi_status acpi_ev_acquire_global_lock(u16 timeout)
 {
@@ -409,11 +439,26 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout)
         * Only one thread can acquire the GL at a time, the global_lock_mutex
         * enforces this. This interface releases the interpreter if we must wait.
         */
-       status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, timeout);
+       status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, 0);
+       if (status == AE_TIME) {
+               if (acpi_ev_global_lock_thread_id == acpi_os_get_thread_id()) {
+                       acpi_ev_global_lock_acquired++;
+                       return AE_OK;
+               }
+       }
+
+       if (ACPI_FAILURE(status)) {
+               status =
+                   acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex,
+                                             timeout);
+       }
        if (ACPI_FAILURE(status)) {
                return_ACPI_STATUS(status);
        }
 
+       acpi_ev_global_lock_thread_id = acpi_os_get_thread_id();
+       acpi_ev_global_lock_acquired++;
+
        /*
         * Make sure that a global lock actually exists. If not, just treat
         * the lock as a standard mutex.
@@ -480,6 +525,11 @@ acpi_status acpi_ev_release_global_lock(void)
                return_ACPI_STATUS(AE_NOT_ACQUIRED);
        }
 
+       acpi_ev_global_lock_acquired--;
+       if (acpi_ev_global_lock_acquired > 0) {
+               return AE_OK;
+       }
+
        if (acpi_gbl_global_lock_present) {
 
                /* Allow any thread to release the lock */
@@ -493,7 +543,7 @@ acpi_status acpi_ev_release_global_lock(void)
                if (pending) {
                        status =
                            acpi_set_register(ACPI_BITREG_GLOBAL_LOCK_RELEASE,
-                                             1, ACPI_MTX_LOCK);
+                                             1);
                }
 
                ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
@@ -503,7 +553,8 @@ acpi_status acpi_ev_release_global_lock(void)
        acpi_gbl_global_lock_acquired = FALSE;
 
        /* Release the local GL mutex */
-
+       acpi_ev_global_lock_thread_id = NULL;
+       acpi_ev_global_lock_acquired = 0;
        acpi_os_release_mutex(acpi_gbl_global_lock_mutex);
        return_ACPI_STATUS(status);
 }
@@ -554,6 +605,12 @@ void acpi_ev_terminate(void)
                if (ACPI_FAILURE(status)) {
                        ACPI_ERROR((AE_INFO, "Could not remove SCI handler"));
                }
+
+               status = acpi_ev_remove_global_lock_handler();
+               if (ACPI_FAILURE(status)) {
+                       ACPI_ERROR((AE_INFO,
+                                   "Could not remove Global Lock handler"));
+               }
        }
 
        /* Deallocate all handler objects installed within GPE info structs */