patch-2.4.6 linux/drivers/acpi/events/evmisc.c

Next file: linux/drivers/acpi/events/evregion.c
Previous file: linux/drivers/acpi/events/evevent.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/events/evmisc.c linux/drivers/acpi/events/evmisc.c
@@ -2,7 +2,7 @@
  *
  * Module Name: evmisc - ACPI device notification handler dispatch
  *                       and ACPI Global Lock support
- *              $Revision: 22 $
+ *              $Revision: 31 $
  *
  *****************************************************************************/
 
@@ -30,13 +30,13 @@
 #include "acinterp.h"
 #include "achware.h"
 
-#define _COMPONENT          EVENT_HANDLING
+#define _COMPONENT          ACPI_EVENTS
 	 MODULE_NAME         ("evmisc")
 
 
-/**************************************************************************
+/*******************************************************************************
  *
- * FUNCTION:    Acpi_ev_notify_dispatch
+ * FUNCTION:    Acpi_ev_queue_notify_request
  *
  * PARAMETERS:
  *
@@ -45,16 +45,20 @@
  * DESCRIPTION: Dispatch a device notification event to a previously
  *              installed handler.
  *
- *************************************************************************/
+ ******************************************************************************/
 
-void
-acpi_ev_notify_dispatch (
-	ACPI_HANDLE             device,
+ACPI_STATUS
+acpi_ev_queue_notify_request (
+	ACPI_NAMESPACE_NODE     *node,
 	u32                     notify_value)
 {
 	ACPI_OPERAND_OBJECT     *obj_desc;
-	ACPI_OPERAND_OBJECT     *handler_obj;
-	NOTIFY_HANDLER          handler;
+	ACPI_OPERAND_OBJECT     *handler_obj = NULL;
+	ACPI_GENERIC_STATE      *notify_info;
+	ACPI_STATUS             status = AE_OK;
+
+
+	PROC_NAME ("Ev_queue_notify_request");
 
 
 	/*
@@ -64,9 +68,7 @@
 	 * initiate soft-off or sleep operation?
 	 */
 
-
-	switch (notify_value)
-	{
+	switch (notify_value) {
 	case 0:
 		break;
 
@@ -85,67 +87,136 @@
 
 
 	/*
-	 * Invoke a global notify handler if installed.
-	 * This is done _before_ we invoke the per-device handler attached to the device.
+	 * Get the notify object attached to the device Node
 	 */
 
-	if (notify_value <= MAX_SYS_NOTIFY) {
-		/* Global system notification handler */
+	obj_desc = acpi_ns_get_attached_object (node);
+	if (obj_desc) {
 
-		if (acpi_gbl_sys_notify.handler) {
-			acpi_gbl_sys_notify.handler (device, notify_value,
-					  acpi_gbl_sys_notify.context);
+		/* We have the notify object, Get the right handler */
+
+		switch (node->type) {
+		case ACPI_TYPE_DEVICE:
+			if (notify_value <= MAX_SYS_NOTIFY) {
+				handler_obj = obj_desc->device.sys_handler;
+			}
+			else {
+				handler_obj = obj_desc->device.drv_handler;
+			}
+			break;
+
+		case ACPI_TYPE_THERMAL:
+			if (notify_value <= MAX_SYS_NOTIFY) {
+				handler_obj = obj_desc->thermal_zone.sys_handler;
+			}
+			else {
+				handler_obj = obj_desc->thermal_zone.drv_handler;
+			}
+			break;
 		}
 	}
 
-	else {
-		/* Global driver notification handler */
 
-		if (acpi_gbl_drv_notify.handler) {
-			acpi_gbl_drv_notify.handler (device, notify_value,
-					  acpi_gbl_drv_notify.context);
+	/* If there is any handler to run, schedule the dispatcher */
+
+	if ((acpi_gbl_sys_notify.handler && (notify_value <= MAX_SYS_NOTIFY)) ||
+		(acpi_gbl_drv_notify.handler && (notify_value > MAX_SYS_NOTIFY)) ||
+		handler_obj) {
+
+		notify_info = acpi_ut_create_generic_state ();
+		if (!notify_info) {
+			return (AE_NO_MEMORY);
+		}
+
+		notify_info->notify.node      = node;
+		notify_info->notify.value     = (u16) notify_value;
+		notify_info->notify.handler_obj = handler_obj;
+
+		status = acpi_os_queue_for_execution (OSD_PRIORITY_HIGH,
+				  acpi_ev_notify_dispatch, notify_info);
+		if (ACPI_FAILURE (status)) {
+			acpi_ut_delete_generic_state (notify_info);
 		}
 	}
 
+	if (!handler_obj) {
+		/* There is no per-device notify handler for this device */
 
-	/*
-	 * Get the notify object which must be attached to the device Node
-	 */
+	}
 
-	obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) device);
-	if (!obj_desc) {
-		/* There can be no notify handler for this device */
+	return (status);
+}
 
-		return;
-	}
 
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ev_notify_dispatch
+ *
+ * PARAMETERS:
+ *
+ * RETURN:      None.
+ *
+ * DESCRIPTION: Dispatch a device notification event to a previously
+ *              installed handler.
+ *
+ ******************************************************************************/
+
+void
+acpi_ev_notify_dispatch (
+	void                    *context)
+{
+	ACPI_GENERIC_STATE      *notify_info = (ACPI_GENERIC_STATE *) context;
+	ACPI_NOTIFY_HANDLER     global_handler = NULL;
+	void                    *global_context = NULL;
+	ACPI_OPERAND_OBJECT     *handler_obj;
 
-	/* We have the notify object, Get the right handler */
 
-	if (notify_value <= MAX_SYS_NOTIFY) {
-		handler_obj = obj_desc->device.sys_handler;
+	/*
+	 * We will invoke a global notify handler if installed.
+	 * This is done _before_ we invoke the per-device handler attached to the device.
+	 */
+
+	if (notify_info->notify.value <= MAX_SYS_NOTIFY) {
+		/* Global system notification handler */
+
+		if (acpi_gbl_sys_notify.handler) {
+			global_handler = acpi_gbl_sys_notify.handler;
+			global_context = acpi_gbl_sys_notify.context;
+		}
 	}
+
 	else {
-		handler_obj = obj_desc->device.drv_handler;
+		/* Global driver notification handler */
+
+		if (acpi_gbl_drv_notify.handler) {
+			global_handler = acpi_gbl_drv_notify.handler;
+			global_context = acpi_gbl_drv_notify.context;
+		}
 	}
 
-	/* Validate the handler */
 
-	if (!handler_obj) {
-		/* There is no notify handler for this device */
+	/* Invoke the system handler first, if present */
 
-		return;
+	if (global_handler) {
+		global_handler (notify_info->notify.node, notify_info->notify.value, global_context);
 	}
 
-	/* There is a handler, invoke it */
+	/* Now invoke the per-device handler, if present */
 
-	handler = handler_obj->notify_handler.handler;
-	handler (device, notify_value, handler_obj->notify_handler.context);
+	handler_obj = notify_info->notify.handler_obj;
+	if (handler_obj) {
+		handler_obj->notify_handler.handler (notify_info->notify.node, notify_info->notify.value,
+				  handler_obj->notify_handler.context);
+	}
 
+
+	/* All done with the info object */
+
+	acpi_ut_delete_generic_state (notify_info);
 }
 
 
-/***************************************************************************
+/*******************************************************************************
  *
  * FUNCTION:    Acpi_ev_global_lock_thread
  *
@@ -155,7 +226,7 @@
  *              Global Lock.  Simply signal all threads that are waiting
  *              for the lock.
  *
- **************************************************************************/
+ ******************************************************************************/
 
 static void
 acpi_ev_global_lock_thread (
@@ -173,7 +244,7 @@
 }
 
 
-/***************************************************************************
+/*******************************************************************************
  *
  * FUNCTION:    Acpi_ev_global_lock_handler
  *
@@ -183,7 +254,7 @@
  *              release interrupt occurs.  Grab the global lock and queue
  *              the global lock thread for execution
  *
- **************************************************************************/
+ ******************************************************************************/
 
 static u32
 acpi_ev_global_lock_handler (
@@ -216,7 +287,7 @@
 }
 
 
-/***************************************************************************
+/*******************************************************************************
  *
  * FUNCTION:    Acpi_ev_init_global_lock_handler
  *
@@ -224,7 +295,7 @@
  *
  * DESCRIPTION: Install a handler for the global lock release event
  *
- **************************************************************************/
+ ******************************************************************************/
 
 ACPI_STATUS
 acpi_ev_init_global_lock_handler (void)
@@ -232,14 +303,27 @@
 	ACPI_STATUS             status;
 
 
+	acpi_gbl_global_lock_present = TRUE;
 	status = acpi_install_fixed_event_handler (ACPI_EVENT_GLOBAL,
 			  acpi_ev_global_lock_handler, NULL);
 
+	/*
+	 * If the global lock does not exist on this platform, the attempt
+	 * to enable GBL_STS will fail (the GBL_EN bit will not stick)
+	 * Map to AE_OK, but mark global lock as not present.
+	 * Any attempt to actually use the global lock will be flagged
+	 * with an error.
+	 */
+	if (status == AE_NO_HARDWARE_RESPONSE) {
+		acpi_gbl_global_lock_present = FALSE;
+		status = AE_OK;
+	}
+
 	return (status);
 }
 
 
-/***************************************************************************
+/******************************************************************************
  *
  * FUNCTION:    Acpi_ev_acquire_global_lock
  *
@@ -247,7 +331,7 @@
  *
  * DESCRIPTION: Attempt to gain ownership of the Global Lock.
  *
- **************************************************************************/
+ *****************************************************************************/
 
 ACPI_STATUS
 acpi_ev_acquire_global_lock(void)
@@ -257,6 +341,12 @@
 	void                    *global_lock;
 
 
+	/* Make sure that we actually have a global lock */
+
+	if (!acpi_gbl_global_lock_present) {
+		return (AE_NO_GLOBAL_LOCK);
+	}
+
 	/* One more thread wants the global lock */
 
 	acpi_gbl_global_lock_thread_count++;
@@ -283,7 +373,6 @@
 	   /* We got the lock */
 
 		acpi_gbl_global_lock_acquired = TRUE;
-
 		return (AE_OK);
 	}
 
@@ -298,20 +387,19 @@
 	  * Since this wait will block, we must release the interpreter
 	  */
 
-	status = acpi_aml_system_wait_semaphore (acpi_gbl_global_lock_semaphore,
+	status = acpi_ex_system_wait_semaphore (acpi_gbl_global_lock_semaphore,
 			  ACPI_UINT32_MAX);
-
 	return (status);
 }
 
 
-/***************************************************************************
+/*******************************************************************************
  *
  * FUNCTION:    Acpi_ev_release_global_lock
  *
  * DESCRIPTION: Releases ownership of the Global Lock.
  *
- **************************************************************************/
+ ******************************************************************************/
 
 void
 acpi_ev_release_global_lock (void)
@@ -321,7 +409,7 @@
 
 
 	if (!acpi_gbl_global_lock_thread_count) {
-		REPORT_WARNING(("Releasing a non-acquired Global Lock\n"));
+		REPORT_WARNING(("Global Lock has not be acquired, cannot release\n"));
 		return;
 	}
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)