Skip to contentSkip to conversation

ACPICA: Global event handler

PATCH In review Lin Ming 2 participants 2 messages Dec 13, 2010 – Jan 4, 2011

Subsystems (2)
lore
Share & tools
lore

Lin Ming

author
#0 lore raw

PATCH v2 7/8 ACPICA: Global event handler

The global event handler is called whenever a general purpose or fixed ACPI event occurs.

Also update Linux OSL to collect events counter with global event handler.

---
 drivers/acpi/acpica/acglobal.h |    5 ++++
 drivers/acpi/acpica/evevent.c  |   12 ++++++++-
 drivers/acpi/acpica/evgpe.c    |    9 ++++++-
 drivers/acpi/acpica/evxface.c  |   51 ++++++++++++++++++++++++++++++++++++++++
 drivers/acpi/acpica/utglobal.c |    1 +
 drivers/acpi/sysfs.c           |   19 +++++++++++++-
 include/acpi/acpixf.h          |    4 +++
 include/acpi/actypes.h         |    8 ++++++
 8 files changed, 104 insertions(+), 5 deletions(-)
drivers/acpi/acpica/acglobal.h +5 -0
index fc69464..9bb69c5 100644
@@ -146,6 +146,9 @@ u8 acpi_gbl_system_awake_and_running;
 
 extern u32 acpi_gbl_nesting_level;
 
+ACPI_EXTERN u32 acpi_gpe_count;
+ACPI_EXTERN u32 acpi_fixed_event_count[ACPI_NUM_FIXED_EVENTS];
+
 /* Support for dynamic control method tracing mechanism */
 
 ACPI_EXTERN u32 acpi_gbl_original_dbg_level;
@@ -371,6 +374,8 @@ ACPI_EXTERN struct acpi_gpe_xrupt_info *acpi_gbl_gpe_xrupt_list_head;
 ACPI_EXTERN struct acpi_gpe_block_info
 *acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS];
 ACPI_EXTERN u8 acpi_gbl_all_gpes_initialized;
+ACPI_EXTERN ACPI_GBL_EVENT_HANDLER acpi_gbl_global_event_handler;
+ACPI_EXTERN void *acpi_gbl_global_event_handler_context;
 
 /*****************************************************************************
  *
drivers/acpi/acpica/evevent.c +10 -2
index c61c303..e5e313c 100644
@@ -217,9 +217,17 @@ u32 acpi_ev_fixed_event_detect(void)
 		     status_bit_mask)
 		    && (fixed_enable & acpi_gbl_fixed_event_info[i].
 			enable_bit_mask)) {
+			/*
+			 * Found an active (signalled) event. Invoke global event
+			 * handler if present.
+			 */
+			acpi_fixed_event_count[i]++;
+			if (acpi_gbl_global_event_handler) {
+				acpi_gbl_global_event_handler
+				    (ACPI_EVENT_TYPE_FIXED, NULL, i,
+				     acpi_gbl_global_event_handler_context);
+			}
 
-			/* Found an active (signalled) event */
-			acpi_os_fixed_event_count(i);
 			int_status |= acpi_ev_fixed_event_dispatch(i);
 		}
 	}
drivers/acpi/acpica/evgpe.c +8 -1
index 2dbca95..3bcf5ef 100644
@@ -642,7 +642,14 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device,
 
 	ACPI_FUNCTION_TRACE(ev_gpe_dispatch);
 
-	acpi_os_gpe_count(gpe_number);
+	/* Invoke global event handler if present */
+
+	acpi_gpe_count++;
+	if (acpi_gbl_global_event_handler) {
+		acpi_gbl_global_event_handler(ACPI_EVENT_TYPE_GPE, gpe_device,
+					      gpe_number,
+					      acpi_gbl_global_event_handler_context);
+	}
 
 	/*
 	 * If edge-triggered, clear the GPE status bit now. Note that
drivers/acpi/acpica/evxface.c +51 -0

57 lines not on this page · raw message

drivers/acpi/acpica/utglobal.c +1 -0
index a99c32a..508537f 100644
@@ -778,6 +778,7 @@ acpi_status acpi_ut_init_globals(void)
 	acpi_gbl_init_handler = NULL;
 	acpi_gbl_table_handler = NULL;
 	acpi_gbl_interface_handler = NULL;
+	acpi_gbl_global_event_handler = NULL;
 
 	/* Global Lock support */
 
drivers/acpi/sysfs.c +17 -2
index f8588f8..61891e7 100644
@@ -438,7 +438,7 @@ static void delete_gpe_attr_array(void)
 	return;
 }
 
-void acpi_os_gpe_count(u32 gpe_number)
+static void gpe_count(u32 gpe_number)
 {
 	acpi_gpe_count++;
 
@@ -454,7 +454,7 @@ void acpi_os_gpe_count(u32 gpe_number)
 	return;
 }
 
-void acpi_os_fixed_event_count(u32 event_number)
+static void fixed_event_count(u32 event_number)
 {
 	if (!all_counters)
 		return;
@@ -468,6 +468,16 @@ void acpi_os_fixed_event_count(u32 event_number)
 	return;
 }
 
+static void acpi_gbl_event_handler(u32 event_type, acpi_handle device,
+	u32 event_number, void *context)
+{
+	if (event_type == ACPI_EVENT_TYPE_GPE)
+		gpe_count(event_number);
+
+	if (event_type == ACPI_EVENT_TYPE_FIXED)
+		fixed_event_count(event_number);
+}
+
 static int get_status(u32 index, acpi_event_status *status,
 		      acpi_handle *handle)
 {
@@ -601,6 +611,7 @@ end:
 
 void acpi_irq_stats_init(void)
 {
+	acpi_status status;
 	int i;
 
 	if (all_counters)
@@ -619,6 +630,10 @@ void acpi_irq_stats_init(void)
 	if (all_counters == NULL)
 		goto fail;
 
+	status = acpi_install_global_event_handler(acpi_gbl_event_handler, NULL);
+	if (ACPI_FAILURE(status))
+		goto fail;
+
 	counter_attrs = kzalloc(sizeof(struct kobj_attribute) * (num_counters),
 				GFP_KERNEL);
 	if (counter_attrs == NULL)
include/acpi/acpixf.h +4 -0
index 9de6a17..e8142d5 100644
@@ -229,6 +229,10 @@ acpi_status
 acpi_install_initialization_handler(acpi_init_handler handler, u32 function);
 
 acpi_status
+acpi_install_global_event_handler(ACPI_GBL_EVENT_HANDLER handler,
+				 void *context);
+
+acpi_status
 acpi_install_fixed_event_handler(u32 acpi_event,
 				 acpi_event_handler handler, void *context);
 
include/acpi/actypes.h +8 -0
index d7274ee..939a431 100644
@@ -895,6 +895,14 @@ typedef void
 /*
  * Various handlers and callback procedures
  */
+typedef
+void (*ACPI_GBL_EVENT_HANDLER) (u32 event_type,
+			       acpi_handle device,
+			       u32 event_number, void *context);
+
+#define ACPI_EVENT_TYPE_GPE         0
+#define ACPI_EVENT_TYPE_FIXED       1
+
 typedef u32(*acpi_event_handler) (void *context);
 
 typedef
Signature · 1 line
1.5.3
#1 lore raw

PATCH 1/1 ACPI / ACPICA: Collect event statistics in respective event structures

From: Rafael J. Wysocki <[email protected]>

Fixed event and GPE statistics are collected with the help of two functions, acpi_os_fixed_event_count and acpi_os_gpe_count(), that ACPICA expects the host OS to define. Thus every host OS that wants to collect such statistics has to provide its own functions for this purpose, which is going to lead to unnecessary code duplication in the long run. Moreover, the interfaces used by host OSes to get event status information can be extended in a straightforward way to also return the event statistics provided that those statistics are collected at the ACPICA level.

Extend struct acpi_gpe_event_info and struct acpi_fixed_event_info so that event statistics can be stored in these structures. Modify acpi_ev_gpe_dispatch() and acpi_ev_fixed_event_dispatch() so that they increment GPE and fixed event counters, respectively, instead of calling acpi_os_gpe_count() and acpi_os_fixed_event_count(). Add functions allowing the host OS to modify the GPE and event counters and functions. Add total GPE event counter and functions for manipulating it.

Modify acpi_get_event_status() and acpi_get_gpe_status() to return current values of the appropriate event counters, if necessary, in addition to the "usual" event status information.

Rework the kernel's code reporting GPE and fixed event statistics through sysfs to take the above changes into account.

---

Hi Len,

This patch is a replacement for
http://git.kernel.org/?p=linux/kernel/git/lenb/linux-acpi-2.6.git;a=commit;h=c891ca193fa2449945c3ba00cd125b5f50c0337d

It should apply on top of your tree with the ACPICA branch removed, rebased on top of the Linus' tree and reapplied (including
https://patchwork.kernel.org/patch/449211/ instead of the original).

In case it doesn't, I can post my version of the ACPICA branch (rebased on top of the Linus' tree and with a couple of fixes), so please let me know.

Thanks,
Rafael

---
 drivers/acpi/acpica/aclocal.h  |    7 ++
 drivers/acpi/acpica/evevent.c  |    3 -
 drivers/acpi/acpica/evgpe.c    |   37 ++++++++++++++
 drivers/acpi/acpica/evxfevnt.c |   33 ++++++++++++
 drivers/acpi/acpica/evxfgpe.c  |   44 ++++++++++++++++-
 drivers/acpi/scan.c            |    2 
 drivers/acpi/sysfs.c           |  105 +++++++++++++++--------------------------
 include/acpi/acpiosxf.h        |    3 -
 include/acpi/acpixf.h          |   14 ++++-
 9 files changed, 173 insertions(+), 75 deletions(-)
drivers/acpi/acpica/aclocal.h +7 -0
Index: linux-2.6/drivers/acpi/acpica/aclocal.h
===================================================================
@@ -406,6 +406,11 @@ struct acpi_predefined_data {
  *
  ****************************************************************************/
 
+/* Event statistics. */
+struct acpi_event_stats {
+	u32 count;
+};
+
 /* Dispatch info for each GPE -- either a method or handler, cannot be both */
 
 struct acpi_gpe_handler_info {
@@ -432,6 +437,7 @@ struct acpi_gpe_event_info {
 	u8 flags;		/* Misc info about this GPE */
 	u8 gpe_number;		/* This GPE */
 	u8 runtime_count;	/* References to a run GPE */
+	struct acpi_event_stats stats;	/* GPE event statistics */
 };
 
 /* Information about a GPE register pair, one per each status/enable pair in an array */
@@ -501,6 +507,7 @@ struct acpi_fixed_event_info {
 	u8 enable_register_id;
 	u16 status_bit_mask;
 	u16 enable_bit_mask;
+	struct acpi_event_stats stats;	/* Fixed event statistics */
 };
 
 /* Information used during field processing */
drivers/acpi/acpica/evgpe.c +36 -1
Index: linux-2.6/drivers/acpi/acpica/evgpe.c
===================================================================
@@ -638,6 +638,7 @@ acpi_status acpi_ev_finish_gpe(struct ac
  *              This function executes at interrupt level.
  *
  ******************************************************************************/
+static struct acpi_event_stats acpi_ev_gpe_stats;
 
 u32
 acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device,
@@ -648,7 +649,8 @@ acpi_ev_gpe_dispatch(struct acpi_namespa
 
 	ACPI_FUNCTION_TRACE(ev_gpe_dispatch);
 
-	acpi_os_gpe_count(gpe_number);
+	gpe_event_info->stats.count++;
+	acpi_ev_gpe_stats.count++;
 
 	/*
 	 * If edge-triggered, clear the GPE status bit now. Note that
@@ -739,3 +741,36 @@ acpi_ev_gpe_dispatch(struct acpi_namespa
 
 	return_UINT32(ACPI_INTERRUPT_HANDLED);
 }
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_total_gpe_stats_count
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      Current value of the total GPE events counter.
+ *
+ * DESCRIPTION: Return the counted number of GPE events.
+ *
+ ******************************************************************************/
+u32 acpi_total_gpe_stats_count(void)
+{
+	return acpi_ev_gpe_stats.count;
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_total_gpe_stats_count
+ *
+ * PARAMETERS:  gpe_device      - New value of the total GPE events counter.
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Set the total GPE events counter to the given value.
+ *
+ ******************************************************************************/
+void acpi_set_total_gpe_stats_count(u32 count)
+{
+	acpi_ev_gpe_stats.count = count;
+}
include/acpi/acpixf.h +12 -2
Index: linux-2.6/include/acpi/acpixf.h
===================================================================
@@ -283,7 +283,10 @@ acpi_status acpi_disable_event(u32 event
 
 acpi_status acpi_clear_event(u32 event);
 
-acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status);
+acpi_status acpi_get_event_status(u32 event,
+				  acpi_event_status *event_status, u32 *count);
+
+acpi_status acpi_set_event_stats_count(u32 event, u32 count);
 
 /*
  * GPE Interfaces
@@ -302,7 +305,10 @@ acpi_status acpi_set_gpe_wake_mask(acpi_
 
 acpi_status
 acpi_get_gpe_status(acpi_handle gpe_device,
-		    u32 gpe_number, acpi_event_status *event_status);
+		    u32 gpe_number, acpi_event_status *event_status, u32 *count);
+
+acpi_status acpi_set_gpe_stats_count(acpi_handle gpe_device, u32 gpe_number,
+				     u32 count);
 
 acpi_status acpi_disable_all_gpes(void);
 
@@ -319,6 +325,10 @@ acpi_status acpi_remove_gpe_block(acpi_h
 
 acpi_status acpi_update_all_gpes(void);
 
+u32 acpi_total_gpe_stats_count(void);
+
+void acpi_set_total_gpe_stats_count(u32 count);
+
 /*
  * Resource interfaces
  */
drivers/acpi/sysfs.c +40 -65

190 lines not on this page · raw message

drivers/acpi/acpica/evxfevnt.c +32 -1
Index: linux-2.6/drivers/acpi/acpica/evxfevnt.c
===================================================================
@@ -302,13 +302,15 @@ ACPI_EXPORT_SYMBOL(acpi_clear_event)
  * PARAMETERS:  Event           - The fixed event
  *              event_status    - Where the current status of the event will
  *                                be returned
+ *              count           - Where to store the current event counter value
  *
  * RETURN:      Status
  *
  * DESCRIPTION: Obtains and returns the current status of the event
  *
  ******************************************************************************/
-acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status)
+acpi_status acpi_get_event_status(u32 event,
+				  acpi_event_status *event_status, u32 *count)
 {
 	acpi_status status = AE_OK;
 	u32 value;
@@ -347,7 +349,36 @@ acpi_status acpi_get_event_status(u32 ev
 	if (acpi_gbl_fixed_event_handlers[event].handler)
 		*event_status |= ACPI_EVENT_FLAG_HANDLE;
 
+	if (count)
+		*count = acpi_gbl_fixed_event_info[event].stats.count;
+
 	return_ACPI_STATUS(status);
 }
 
 ACPI_EXPORT_SYMBOL(acpi_get_event_status)
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_set_event_stats_count
+ *
+ * PARAMETERS:  Event           - The fixed event
+ *              count           - New value of the event counter
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Set the event counter of the given fixed event to a new value.
+ *
+ ******************************************************************************/
+acpi_status acpi_set_event_stats_count(u32 event, u32 count)
+{
+	ACPI_FUNCTION_TRACE(acpi_set_event_stats_count);
+
+	if (event > ACPI_EVENT_MAX) {
+		return_ACPI_STATUS(AE_BAD_PARAMETER);
+	}
+
+	acpi_gbl_fixed_event_info[event].stats.count = count;
+
+	return_ACPI_STATUS(AE_OK);
+}
+ACPI_EXPORT_SYMBOL(acpi_set_event_stats_count)
drivers/acpi/acpica/evxfgpe.c +43 -1

68 lines not on this page · raw message

drivers/acpi/scan.c +1 -1
Index: linux-2.6/drivers/acpi/scan.c
===================================================================
@@ -809,7 +809,7 @@ static void acpi_bus_set_run_wake_flags(
 
 	status = acpi_get_gpe_status(device->wakeup.gpe_device,
 					device->wakeup.gpe_number,
-						&event_status);
+						&event_status, NULL);
 	if (status == AE_OK)
 		device->wakeup.flags.run_wake =
 				!!(event_status & ACPI_EVENT_FLAG_HANDLE);
drivers/acpi/acpica/evevent.c +2 -1
Index: linux-2.6/drivers/acpi/acpica/evevent.c
===================================================================
@@ -219,7 +219,6 @@ u32 acpi_ev_fixed_event_detect(void)
 			enable_bit_mask)) {
 
 			/* Found an active (signalled) event */
-			acpi_os_fixed_event_count(i);
 			int_status |= acpi_ev_fixed_event_dispatch(i);
 		}
 	}
@@ -245,6 +244,8 @@ static u32 acpi_ev_fixed_event_dispatch(
 
 	ACPI_FUNCTION_ENTRY();
 
+	acpi_gbl_fixed_event_info[event].stats.count++;
+
 	/* Clear the status bit */
 
 	(void)acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
include/acpi/acpiosxf.h +0 -3
Index: linux-2.6/include/acpi/acpiosxf.h
===================================================================
@@ -177,9 +177,6 @@ acpi_os_install_interrupt_handler(u32 gs
 acpi_status
 acpi_os_remove_interrupt_handler(u32 gsi, acpi_osd_handler service_routine);
 
-void acpi_os_gpe_count(u32 gpe_number);
-void acpi_os_fixed_event_count(u32 fixed_event_number);
-
 /*
  * Threads and Scheduling
  */