===================================================================
@@ -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 */
===================================================================
@@ -640,6 +640,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,
@@ -650,9 +651,11 @@ acpi_ev_gpe_dispatch(struct acpi_namespa
ACPI_FUNCTION_TRACE(ev_gpe_dispatch);
+ gpe_event_info->stats.count++;
+ acpi_ev_gpe_stats.count++;
+
/* 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,
@@ -748,3 +751,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;
+}
===================================================================
@@ -287,7 +287,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
@@ -306,7 +309,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);
@@ -323,6 +329,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
*/
===================================================================
@@ -406,11 +406,9 @@ struct event_counter {
u32 flags;
};
-static struct event_counter *all_counters;
static u32 num_gpes;
static u32 num_counters;
static struct attribute **all_attrs;
-static u32 acpi_gpe_count;
static struct attribute_group interrupt_stats_attr_group = {
.name = "interrupts",
@@ -420,11 +418,6 @@ static struct kobj_attribute *counter_at
static void delete_gpe_attr_array(void)
{
- struct event_counter *tmp = all_counters;
-
- all_counters = NULL;
- kfree(tmp);
-
if (counter_attrs) {
int i;
@@ -438,47 +431,7 @@ static void delete_gpe_attr_array(void)
return;
}
-static void gpe_count(u32 gpe_number)
-{
- acpi_gpe_count++;
-
- if (!all_counters)
- return;
-
- if (gpe_number < num_gpes)
- all_counters[gpe_number].count++;
- else
- all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS +
- COUNT_ERROR].count++;
-
- return;
-}
-
-static void fixed_event_count(u32 event_number)
-{
- if (!all_counters)
- return;
-
- if (event_number < ACPI_NUM_FIXED_EVENTS)
- all_counters[num_gpes + event_number].count++;
- else
- all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS +
- COUNT_ERROR].count++;
-
- 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,
+static int get_status(u32 index, acpi_event_status *status, u32 *count,
acpi_handle *handle)
{
int result = 0;
@@ -493,9 +446,9 @@ static int get_status(u32 index, acpi_ev
"Invalid GPE 0x%x\n", index));
goto end;
}
- result = acpi_get_gpe_status(*handle, index, status);
+ result = acpi_get_gpe_status(*handle, index, status, count);
} else if (index < (num_gpes + ACPI_NUM_FIXED_EVENTS))
- result = acpi_get_event_status(index - num_gpes, status);
+ result = acpi_get_event_status(index - num_gpes, status, count);
end:
return result;
@@ -505,27 +458,38 @@ static ssize_t counter_show(struct kobje
struct kobj_attribute *attr, char *buf)
{
int index = attr - counter_attrs;
- int size;
+ int size = 0;
acpi_handle handle;
acpi_event_status status;
+ u32 count;
int result = 0;
- all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI].count =
- acpi_irq_handled;
- all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI_NOT].count =
- acpi_irq_not_handled;
- all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_GPE].count =
- acpi_gpe_count;
- size = sprintf(buf, "%8d", all_counters[index].count);
-
/* "gpe_all" or "sci" */
- if (index >= num_gpes + ACPI_NUM_FIXED_EVENTS)
+ if (index >= num_gpes + ACPI_NUM_FIXED_EVENTS) {
+ index -= num_gpes + ACPI_NUM_FIXED_EVENTS;
+ switch (index) {
+ case COUNT_GPE:
+ count = acpi_total_gpe_stats_count();
+ break;
+ case COUNT_SCI:
+ count = acpi_irq_handled;
+ break;
+ case COUNT_SCI_NOT:
+ count = acpi_irq_not_handled;
+ break;
+ default:
+ goto end;
+ }
+ size = sprintf(buf, "%8d", count);
goto end;
+ }
- result = get_status(index, &status, &handle);
+ result = get_status(index, &status, &count, &handle);
if (result)
goto end;
+ size = sprintf(buf, "%8d", count);
+
if (!(status & ACPI_EVENT_FLAG_HANDLE))
size += sprintf(buf + size, " invalid");
else if (status & ACPI_EVENT_FLAG_ENABLED)
@@ -551,21 +515,26 @@ static ssize_t counter_set(struct kobjec
{
int index = attr - counter_attrs;
acpi_event_status status;
+ u32 count;
acpi_handle handle;
int result = 0;
if (index == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI) {
int i;
- for (i = 0; i < num_counters; ++i)
- all_counters[i].count = 0;
- acpi_gpe_count = 0;
+ for (i = 0; i < num_gpes; ++i) {
+ if (!acpi_get_gpe_device(index, &handle))
+ acpi_set_gpe_stats_count(handle, index, 0);
+ }
+ for (i = num_gpes; i < num_gpes + ACPI_NUM_FIXED_EVENTS; ++i)
+ acpi_set_event_stats_count(index, 0);
+ acpi_set_total_gpe_stats_count(0);
acpi_irq_handled = 0;
acpi_irq_not_handled = 0;
goto end;
}
/* show the event status for both GPEs and Fixed Events */
- result = get_status(index, &status, &handle);
+ result = get_status(index, &status, &count, &handle);
if (result)
goto end;
@@ -586,7 +555,8 @@ static ssize_t counter_set(struct kobjec
(status & ACPI_EVENT_FLAG_SET))
result = acpi_clear_gpe(handle, index);
else
- all_counters[index].count = strtoul(buf, NULL, 0);
+ acpi_set_gpe_stats_count(handle, index,
+ strtoul(buf, NULL, 0));
} else if (index < num_gpes + ACPI_NUM_FIXED_EVENTS) {
int event = index - num_gpes;
if (!strcmp(buf, "disable\n") &&
@@ -599,9 +569,9 @@ static ssize_t counter_set(struct kobjec
(status & ACPI_EVENT_FLAG_SET))
result = acpi_clear_event(event);
else
- all_counters[index].count = strtoul(buf, NULL, 0);
- } else
- all_counters[index].count = strtoul(buf, NULL, 0);
+ acpi_set_event_stats_count(index,
+ strtoul(buf, NULL, 0));
+ }
if (ACPI_FAILURE(result))
result = -EINVAL;
@@ -611,10 +581,9 @@ end:
void acpi_irq_stats_init(void)
{
- acpi_status status;
int i;
- if (all_counters)
+ if (all_attrs)
return;
num_gpes = acpi_current_gpe_count;
@@ -625,15 +594,6 @@ void acpi_irq_stats_init(void)
if (all_attrs == NULL)
return;
- all_counters = kzalloc(sizeof(struct event_counter) * (num_counters),
- GFP_KERNEL);
- 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)
===================================================================
@@ -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)
===================================================================
@@ -375,6 +375,7 @@ ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
* gpe_number - GPE level within the GPE block
* event_status - Where the current status of the event will
* be returned
+ * count - Where to store the current event counter value
*
* RETURN: Status
*
@@ -383,7 +384,7 @@ ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
******************************************************************************/
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 status = AE_OK;
struct acpi_gpe_event_info *gpe_event_info;
@@ -408,6 +409,9 @@ acpi_get_gpe_status(acpi_handle gpe_devi
if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)
*event_status |= ACPI_EVENT_FLAG_HANDLE;
+ if (count)
+ *count = gpe_event_info->stats.count;
+
unlock_and_exit:
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
return_ACPI_STATUS(status);
@@ -415,6 +419,44 @@ acpi_get_gpe_status(acpi_handle gpe_devi
ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_set_gpe_stats_count
+ *
+ * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
+ * gpe_number - GPE level within the GPE block
+ * count - New value of the event counter
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Set the event counter of the given GPE to a new value.
+ *
+ ******************************************************************************/
+acpi_status acpi_set_gpe_stats_count(acpi_handle gpe_device, u32 gpe_number,
+ u32 count)
+{
+ struct acpi_gpe_event_info *gpe_event_info;
+ acpi_cpu_flags flags;
+ acpi_status status = AE_OK;
+
+ ACPI_FUNCTION_TRACE(acpi_set_gpe_stats_count);
+
+ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
+
+ /* Ensure that we have a valid GPE number */
+
+ gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
+ if (gpe_event_info) {
+ gpe_event_info->stats.count = count;
+ } else {
+ status = AE_BAD_PARAMETER;
+ }
+
+ acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
+ return_ACPI_STATUS(status);
+}
+ACPI_EXPORT_SYMBOL(acpi_set_gpe_stats_count)
+
/******************************************************************************
*
* FUNCTION: acpi_disable_all_gpes
===================================================================
@@ -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);
===================================================================
@@ -221,7 +221,6 @@ u32 acpi_ev_fixed_event_detect(void)
* 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,
@@ -253,6 +252,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].
===================================================================
@@ -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
*/
===================================================================
@@ -146,9 +146,6 @@ 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;