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>
This commit is contained in:
Nate Lawson 2008-01-12 22:13:12 +00:00
parent 66244a7bdd
commit 265ed03ff5
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor-sys/acpica/dist/; revision=175256

View File

@ -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;
}