summaryrefslogtreecommitdiff
path: root/source/components/events
diff options
context:
space:
mode:
authorJung-uk Kim <jkim@FreeBSD.org>2012-06-20 17:51:04 +0000
committerJung-uk Kim <jkim@FreeBSD.org>2012-06-20 17:51:04 +0000
commit705c538931446b23ef7f028f71c9da55c78bbf23 (patch)
treef634c2ad6dfa6f49c5aaabc64f8bb79b74dda5a7 /source/components/events
parentfa948a817cf9dae39dc632f9bf48a8af37244a0e (diff)
Notes
Diffstat (limited to 'source/components/events')
-rw-r--r--source/components/events/evgpe.c15
-rw-r--r--source/components/events/evgpeutil.c19
-rw-r--r--source/components/events/evxfgpe.c70
3 files changed, 88 insertions, 16 deletions
diff --git a/source/components/events/evgpe.c b/source/components/events/evgpe.c
index a3781a55c66b..623795a83619 100644
--- a/source/components/events/evgpe.c
+++ b/source/components/events/evgpe.c
@@ -518,6 +518,7 @@ AcpiEvAsynchExecuteGpeMethod (
ACPI_STATUS Status;
ACPI_GPE_EVENT_INFO *LocalGpeEventInfo;
ACPI_EVALUATE_INFO *Info;
+ ACPI_GPE_NOTIFY_INFO *Notify;
ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod);
@@ -573,10 +574,18 @@ AcpiEvAsynchExecuteGpeMethod (
* completes. The notify handlers are NOT invoked synchronously
* from this thread -- because handlers may in turn run other
* control methods.
+ *
+ * June 2012: Expand implicit notify mechanism to support
+ * notifies on multiple device objects.
*/
- Status = AcpiEvQueueNotifyRequest (
- LocalGpeEventInfo->Dispatch.DeviceNode,
- ACPI_NOTIFY_DEVICE_WAKE);
+ Notify = LocalGpeEventInfo->Dispatch.NotifyList;
+ while (ACPI_SUCCESS (Status) && Notify)
+ {
+ Status = AcpiEvQueueNotifyRequest (Notify->DeviceNode,
+ ACPI_NOTIFY_DEVICE_WAKE);
+
+ Notify = Notify->Next;
+ }
break;
case ACPI_GPE_DISPATCH_METHOD:
diff --git a/source/components/events/evgpeutil.c b/source/components/events/evgpeutil.c
index 70580cd853c9..00057350c46a 100644
--- a/source/components/events/evgpeutil.c
+++ b/source/components/events/evgpeutil.c
@@ -391,6 +391,8 @@ AcpiEvDeleteGpeHandlers (
void *Context)
{
ACPI_GPE_EVENT_INFO *GpeEventInfo;
+ ACPI_GPE_NOTIFY_INFO *Notify;
+ ACPI_GPE_NOTIFY_INFO *Next;
UINT32 i;
UINT32 j;
@@ -412,10 +414,27 @@ AcpiEvDeleteGpeHandlers (
if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
ACPI_GPE_DISPATCH_HANDLER)
{
+ /* Delete an installed handler block */
+
ACPI_FREE (GpeEventInfo->Dispatch.Handler);
GpeEventInfo->Dispatch.Handler = NULL;
GpeEventInfo->Flags &= ~ACPI_GPE_DISPATCH_MASK;
}
+ else if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
+ ACPI_GPE_DISPATCH_NOTIFY)
+ {
+ /* Delete the implicit notification device list */
+
+ Notify = GpeEventInfo->Dispatch.NotifyList;
+ while (Notify)
+ {
+ Next = Notify->Next;
+ ACPI_FREE (Notify);
+ Notify = Next;
+ }
+ GpeEventInfo->Dispatch.NotifyList = NULL;
+ GpeEventInfo->Flags &= ~ACPI_GPE_DISPATCH_MASK;
+ }
}
}
diff --git a/source/components/events/evxfgpe.c b/source/components/events/evxfgpe.c
index c0dd88c77752..daea88804ddb 100644
--- a/source/components/events/evxfgpe.c
+++ b/source/components/events/evxfgpe.c
@@ -295,9 +295,10 @@ AcpiSetupGpeForWake (
ACPI_HANDLE GpeDevice,
UINT32 GpeNumber)
{
- ACPI_STATUS Status = AE_BAD_PARAMETER;
+ ACPI_STATUS Status;
ACPI_GPE_EVENT_INFO *GpeEventInfo;
ACPI_NAMESPACE_NODE *DeviceNode;
+ ACPI_GPE_NOTIFY_INFO *Notify;
ACPI_CPU_FLAGS Flags;
@@ -338,26 +339,69 @@ AcpiSetupGpeForWake (
/* Ensure that we have a valid GPE number */
GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
- if (GpeEventInfo)
+ if (!GpeEventInfo)
+ {
+ Status = AE_BAD_PARAMETER;
+ goto UnlockAndExit;
+ }
+
+ /*
+ * If there is no method or handler for this GPE, then the
+ * WakeDevice will be notified whenever this GPE fires. This is
+ * known as an "implicit notify". Note: The GPE is assumed to be
+ * level-triggered (for windows compatibility).
+ */
+ if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
+ ACPI_GPE_DISPATCH_NONE)
{
/*
- * If there is no method or handler for this GPE, then the
- * WakeDevice will be notified whenever this GPE fires (aka
- * "implicit notify") Note: The GPE is assumed to be
- * level-triggered (for windows compatibility).
+ * This is the first device for implicit notify on this GPE.
+ * Just set the flags here, and enter the NOTIFY block below.
*/
- if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
- ACPI_GPE_DISPATCH_NONE)
+ GpeEventInfo->Flags =
+ (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED);
+ }
+
+ /*
+ * If we already have an implicit notify on this GPE, add
+ * this device to the notify list.
+ */
+ if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
+ ACPI_GPE_DISPATCH_NOTIFY)
+ {
+ /* Ensure that the device is not already in the list */
+
+ Notify = GpeEventInfo->Dispatch.NotifyList;
+ while (Notify)
{
- GpeEventInfo->Flags =
- (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED);
- GpeEventInfo->Dispatch.DeviceNode = DeviceNode;
+ if (Notify->DeviceNode == DeviceNode)
+ {
+ Status = AE_ALREADY_EXISTS;
+ goto UnlockAndExit;
+ }
+ Notify = Notify->Next;
}
- GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
- Status = AE_OK;
+ /* Add this device to the notify list for this GPE */
+
+ Notify = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_NOTIFY_INFO));
+ if (!Notify)
+ {
+ Status = AE_NO_MEMORY;
+ goto UnlockAndExit;
+ }
+
+ Notify->DeviceNode = DeviceNode;
+ Notify->Next = GpeEventInfo->Dispatch.NotifyList;
+ GpeEventInfo->Dispatch.NotifyList = Notify;
}
+ /* Mark the GPE as a possible wake event */
+
+ GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
+ Status = AE_OK;
+
+UnlockAndExit:
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
return_ACPI_STATUS (Status);
}