summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornjl <njl@FreeBSD.org>2008-01-12 22:13:12 +0000
committernjl <njl@FreeBSD.org>2008-01-12 22:13:12 +0000
commitcec3f46f5f61173a687aa7e171b0ac680707a164 (patch)
tree0f7802d7790db0973016152a58719d4da3569b85
parentf7e7ed217a2b7448cff8a8a04a276fb8f8be8209 (diff)
downloadFreeBSD-src-cec3f46f5f61173a687aa7e171b0ac680707a164.zip
FreeBSD-src-cec3f46f5f61173a687aa7e171b0ac680707a164.tar.gz
Fix GPE livelock that occurs on HP/Compaq laptops, mostly in the thermal
zone code. The GPE handler method (i.e. _L00) generates various Notify events that need to be run to completion before the GPE is re-enabled. In ACPI-CA, we queue an asynch callback at the same priority as a Notify so that it will only run after all Notify handlers have completed. The callback re-enables the GPE afterwards. We also changed the priority of Notifies to be the same as GPEs, given the possibility that another GPE could arrive before the Notifies have completed and we don't want it to get queued ahead of the rest. The ACPI-CA change was submitted by Alexey Starikovskiy (SUSE) and will appear in a later release. Special thanks to him for helping track this bug down. MFC after: 1 week Tested by: jhb, Yousif Hassan <yousif / alumni.jmu.edu>
-rw-r--r--sys/contrib/dev/acpica/evgpe.c22
1 files changed, 19 insertions, 3 deletions
diff --git a/sys/contrib/dev/acpica/evgpe.c b/sys/contrib/dev/acpica/evgpe.c
index e470eae..d18a1d7 100644
--- a/sys/contrib/dev/acpica/evgpe.c
+++ b/sys/contrib/dev/acpica/evgpe.c
@@ -123,6 +123,10 @@
/* Local prototypes */
+static void
+AcpiEvAsynchEnableGpe (
+ void *Context);
+
static void ACPI_SYSTEM_XFACE
AcpiEvAsynchExecuteGpeMethod (
void *Context);
@@ -684,14 +688,26 @@ AcpiEvAsynchExecuteGpeMethod (
}
}
- if ((LocalGpeEventInfo.Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
+ /* Defer enabling of GPE until all notify handlers are done */
+ AcpiOsExecute(OSL_NOTIFY_HANDLER, AcpiEvAsynchEnableGpe, GpeEventInfo);
+ return_VOID;
+}
+
+static void
+AcpiEvAsynchEnableGpe (
+ void *Context)
+{
+ ACPI_GPE_EVENT_INFO *GpeEventInfo = (void *) Context;
+ ACPI_STATUS Status;
+
+ if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
ACPI_GPE_LEVEL_TRIGGERED)
{
/*
* GPE is level-triggered, we clear the GPE status bit after
* handling the event.
*/
- Status = AcpiHwClearGpe (&LocalGpeEventInfo);
+ Status = AcpiHwClearGpe (GpeEventInfo);
if (ACPI_FAILURE (Status))
{
return_VOID;
@@ -700,7 +716,7 @@ AcpiEvAsynchExecuteGpeMethod (
/* Enable this GPE */
- (void) AcpiHwWriteGpeEnableReg (&LocalGpeEventInfo);
+ (void) AcpiHwWriteGpeEnableReg (GpeEventInfo);
return_VOID;
}
OpenPOWER on IntegriCloud