summaryrefslogtreecommitdiffstats
path: root/sys/contrib/dev/acpica/events/evgpe.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/dev/acpica/events/evgpe.c')
-rw-r--r--sys/contrib/dev/acpica/events/evgpe.c291
1 files changed, 109 insertions, 182 deletions
diff --git a/sys/contrib/dev/acpica/events/evgpe.c b/sys/contrib/dev/acpica/events/evgpe.c
index 4835568..0ece12c 100644
--- a/sys/contrib/dev/acpica/events/evgpe.c
+++ b/sys/contrib/dev/acpica/events/evgpe.c
@@ -134,71 +134,20 @@ AcpiEvAsynchEnableGpe (
/*******************************************************************************
*
- * FUNCTION: AcpiEvSetGpeType
- *
- * PARAMETERS: GpeEventInfo - GPE to set
- * Type - New type
- *
- * RETURN: Status
- *
- * DESCRIPTION: Sets the new type for the GPE (wake, run, or wake/run)
- *
- ******************************************************************************/
-
-ACPI_STATUS
-AcpiEvSetGpeType (
- ACPI_GPE_EVENT_INFO *GpeEventInfo,
- UINT8 Type)
-{
- ACPI_STATUS Status;
-
-
- ACPI_FUNCTION_TRACE (EvSetGpeType);
-
-
- /* Validate type and update register enable masks */
-
- switch (Type)
- {
- case ACPI_GPE_TYPE_WAKE:
- case ACPI_GPE_TYPE_RUNTIME:
- case ACPI_GPE_TYPE_WAKE_RUN:
- break;
-
- default:
- return_ACPI_STATUS (AE_BAD_PARAMETER);
- }
-
- /* Disable the GPE if currently enabled */
-
- Status = AcpiEvDisableGpe (GpeEventInfo);
-
- /* Clear the type bits and insert the new Type */
-
- GpeEventInfo->Flags &= ~ACPI_GPE_TYPE_MASK;
- GpeEventInfo->Flags |= Type;
- return_ACPI_STATUS (Status);
-}
-
-
-/*******************************************************************************
- *
* FUNCTION: AcpiEvUpdateGpeEnableMasks
*
* PARAMETERS: GpeEventInfo - GPE to update
- * Type - What to do: ACPI_GPE_DISABLE or
- * ACPI_GPE_ENABLE
*
* RETURN: Status
*
- * DESCRIPTION: Updates GPE register enable masks based on the GPE type
+ * DESCRIPTION: Updates GPE register enable masks based upon whether there are
+ * references (either wake or run) to this GPE
*
******************************************************************************/
ACPI_STATUS
AcpiEvUpdateGpeEnableMasks (
- ACPI_GPE_EVENT_INFO *GpeEventInfo,
- UINT8 Type)
+ ACPI_GPE_EVENT_INFO *GpeEventInfo)
{
ACPI_GPE_REGISTER_INFO *GpeRegisterInfo;
UINT8 RegisterBit;
@@ -216,36 +165,21 @@ AcpiEvUpdateGpeEnableMasks (
RegisterBit = (UINT8)
(1 << (GpeEventInfo->GpeNumber - GpeRegisterInfo->BaseGpeNumber));
- /* 1) Disable case. Simply clear all enable bits */
+ /* Clear the wake/run bits up front */
- if (Type == ACPI_GPE_DISABLE)
- {
- ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, RegisterBit);
- ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
- return_ACPI_STATUS (AE_OK);
- }
+ ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, RegisterBit);
+ ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
- /* 2) Enable case. Set/Clear the appropriate enable bits */
+ /* Set the mask bits only if there are references to this GPE */
- switch (GpeEventInfo->Flags & ACPI_GPE_TYPE_MASK)
+ if (GpeEventInfo->RuntimeCount)
{
- case ACPI_GPE_TYPE_WAKE:
- ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, RegisterBit);
- ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
- break;
-
- case ACPI_GPE_TYPE_RUNTIME:
- ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, RegisterBit);
- ACPI_SET_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
- break;
-
- case ACPI_GPE_TYPE_WAKE_RUN:
- ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, RegisterBit);
- ACPI_SET_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
- break;
+ ACPI_SET_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
+ }
- default:
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ if (GpeEventInfo->WakeupCount)
+ {
+ ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, RegisterBit);
}
return_ACPI_STATUS (AE_OK);
@@ -257,19 +191,19 @@ AcpiEvUpdateGpeEnableMasks (
* FUNCTION: AcpiEvEnableGpe
*
* PARAMETERS: GpeEventInfo - GPE to enable
- * WriteToHardware - Enable now, or just mark data structs
- * (WAKE GPEs should be deferred)
*
* RETURN: Status
*
- * DESCRIPTION: Enable a GPE based on the GPE type
+ * DESCRIPTION: Hardware-enable a GPE. Always enables the GPE, regardless
+ * of type or number of references.
+ *
+ * Note: The GPE lock should be already acquired when this function is called.
*
******************************************************************************/
ACPI_STATUS
AcpiEvEnableGpe (
- ACPI_GPE_EVENT_INFO *GpeEventInfo,
- BOOLEAN WriteToHardware)
+ ACPI_GPE_EVENT_INFO *GpeEventInfo)
{
ACPI_STATUS Status;
@@ -277,54 +211,37 @@ AcpiEvEnableGpe (
ACPI_FUNCTION_TRACE (EvEnableGpe);
- /* Make sure HW enable masks are updated */
+ /*
+ * We will only allow a GPE to be enabled if it has either an
+ * associated method (_Lxx/_Exx) or a handler. Otherwise, the
+ * GPE will be immediately disabled by AcpiEvGpeDispatch the
+ * first time it fires.
+ */
+ if (!(GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK))
+ {
+ return_ACPI_STATUS (AE_NO_HANDLER);
+ }
+
+ /* Ensure the HW enable masks are current */
- Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo, ACPI_GPE_ENABLE);
+ Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo);
if (ACPI_FAILURE (Status))
{
return_ACPI_STATUS (Status);
}
- /* Mark wake-enabled or HW enable, or both */
+ /* Clear the GPE (of stale events) */
- switch (GpeEventInfo->Flags & ACPI_GPE_TYPE_MASK)
+ Status = AcpiHwClearGpe (GpeEventInfo);
+ if (ACPI_FAILURE (Status))
{
- case ACPI_GPE_TYPE_WAKE:
-
- ACPI_SET_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED);
- break;
-
- case ACPI_GPE_TYPE_WAKE_RUN:
-
- ACPI_SET_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED);
-
- /*lint -fallthrough */
-
- case ACPI_GPE_TYPE_RUNTIME:
-
- ACPI_SET_BIT (GpeEventInfo->Flags, ACPI_GPE_RUN_ENABLED);
-
- if (WriteToHardware)
- {
- /* Clear the GPE (of stale events), then enable it */
-
- Status = AcpiHwClearGpe (GpeEventInfo);
- if (ACPI_FAILURE (Status))
- {
- return_ACPI_STATUS (Status);
- }
-
- /* Enable the requested runtime GPE */
-
- Status = AcpiHwWriteGpeEnableReg (GpeEventInfo);
- }
- break;
-
- default:
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS (Status);
}
- return_ACPI_STATUS (AE_OK);
+ /* Enable the requested GPE */
+
+ Status = AcpiHwWriteGpeEnableReg (GpeEventInfo);
+ return_ACPI_STATUS (Status);
}
@@ -336,7 +253,10 @@ AcpiEvEnableGpe (
*
* RETURN: Status
*
- * DESCRIPTION: Disable a GPE based on the GPE type
+ * DESCRIPTION: Hardware-disable a GPE. Always disables the requested GPE,
+ * regardless of the type or number of references.
+ *
+ * Note: The GPE lock should be already acquired when this function is called.
*
******************************************************************************/
@@ -356,40 +276,14 @@ AcpiEvDisableGpe (
* the GPE behind our back.
*/
- /* Make sure HW enable masks are updated */
+ /* Ensure the HW enable masks are current */
- Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo, ACPI_GPE_DISABLE);
+ Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo);
if (ACPI_FAILURE (Status))
{
return_ACPI_STATUS (Status);
}
- /* Clear the appropriate enabled flags for this GPE */
-
- switch (GpeEventInfo->Flags & ACPI_GPE_TYPE_MASK)
- {
- case ACPI_GPE_TYPE_WAKE:
-
- ACPI_CLEAR_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED);
- break;
-
- case ACPI_GPE_TYPE_WAKE_RUN:
-
- ACPI_CLEAR_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED);
-
- /*lint -fallthrough */
-
- case ACPI_GPE_TYPE_RUNTIME:
-
- /* Disable the requested runtime GPE */
-
- ACPI_CLEAR_BIT (GpeEventInfo->Flags, ACPI_GPE_RUN_ENABLED);
- break;
-
- default:
- break;
- }
-
/*
* Always H/W disable this GPE, even if we don't know the GPE type.
* Simply clear the enable bit for this particular GPE, but do not
@@ -405,6 +299,49 @@ AcpiEvDisableGpe (
/*******************************************************************************
*
+ * FUNCTION: AcpiEvLowGetGpeInfo
+ *
+ * PARAMETERS: GpeNumber - Raw GPE number
+ * GpeBlock - A GPE info block
+ *
+ * RETURN: A GPE EventInfo struct. NULL if not a valid GPE (The GpeNumber
+ * is not within the specified GPE block)
+ *
+ * DESCRIPTION: Returns the EventInfo struct associated with this GPE. This is
+ * the low-level implementation of EvGetGpeEventInfo.
+ *
+ ******************************************************************************/
+
+ACPI_GPE_EVENT_INFO *
+AcpiEvLowGetGpeInfo (
+ UINT32 GpeNumber,
+ ACPI_GPE_BLOCK_INFO *GpeBlock)
+{
+ UINT32 GpeIndex;
+
+
+ /*
+ * Validate that the GpeNumber is within the specified GpeBlock.
+ * (Two steps)
+ */
+ if (!GpeBlock ||
+ (GpeNumber < GpeBlock->BlockBaseNumber))
+ {
+ return (NULL);
+ }
+
+ GpeIndex = GpeNumber - GpeBlock->BlockBaseNumber;
+ if (GpeIndex >= GpeBlock->GpeCount)
+ {
+ return (NULL);
+ }
+
+ return (&GpeBlock->EventInfo[GpeIndex]);
+}
+
+
+/*******************************************************************************
+ *
* FUNCTION: AcpiEvGetGpeEventInfo
*
* PARAMETERS: GpeDevice - Device node. NULL for GPE0/GPE1
@@ -426,7 +363,7 @@ AcpiEvGetGpeEventInfo (
UINT32 GpeNumber)
{
ACPI_OPERAND_OBJECT *ObjDesc;
- ACPI_GPE_BLOCK_INFO *GpeBlock;
+ ACPI_GPE_EVENT_INFO *GpeInfo;
UINT32 i;
@@ -441,16 +378,11 @@ AcpiEvGetGpeEventInfo (
for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++)
{
- GpeBlock = AcpiGbl_GpeFadtBlocks[i];
- if (GpeBlock)
+ GpeInfo = AcpiEvLowGetGpeInfo (GpeNumber,
+ AcpiGbl_GpeFadtBlocks[i]);
+ if (GpeInfo)
{
- if ((GpeNumber >= GpeBlock->BlockBaseNumber) &&
- (GpeNumber < GpeBlock->BlockBaseNumber +
- (GpeBlock->RegisterCount * 8)))
- {
- return (&GpeBlock->EventInfo[GpeNumber -
- GpeBlock->BlockBaseNumber]);
- }
+ return (GpeInfo);
}
}
@@ -468,15 +400,7 @@ AcpiEvGetGpeEventInfo (
return (NULL);
}
- GpeBlock = ObjDesc->Device.GpeBlock;
-
- if ((GpeNumber >= GpeBlock->BlockBaseNumber) &&
- (GpeNumber < GpeBlock->BlockBaseNumber + (GpeBlock->RegisterCount * 8)))
- {
- return (&GpeBlock->EventInfo[GpeNumber - GpeBlock->BlockBaseNumber]);
- }
-
- return (NULL);
+ return (AcpiEvLowGetGpeInfo (GpeNumber, ObjDesc->Device.GpeBlock));
}
@@ -654,9 +578,9 @@ AcpiEvAsynchExecuteGpeMethod (
return_VOID;
}
- /* Set the GPE flags for return to enabled state */
+ /* Update the GPE register masks for return to enabled state */
- (void) AcpiEvEnableGpe (GpeEventInfo, FALSE);
+ (void) AcpiEvUpdateGpeEnableMasks (GpeEventInfo);
/*
* Take a snapshot of the GPE info for this level - we copy the info to
@@ -803,7 +727,7 @@ AcpiEvGpeDispatch (
if (ACPI_FAILURE (Status))
{
ACPI_EXCEPTION ((AE_INFO, Status,
- "Unable to clear GPE[%2X]", GpeNumber));
+ "Unable to clear GPE[0x%2X]", GpeNumber));
return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
}
}
@@ -836,7 +760,7 @@ AcpiEvGpeDispatch (
if (ACPI_FAILURE (Status))
{
ACPI_EXCEPTION ((AE_INFO, Status,
- "Unable to clear GPE[%2X]", GpeNumber));
+ "Unable to clear GPE[0x%2X]", GpeNumber));
return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
}
}
@@ -852,7 +776,7 @@ AcpiEvGpeDispatch (
if (ACPI_FAILURE (Status))
{
ACPI_EXCEPTION ((AE_INFO, Status,
- "Unable to disable GPE[%2X]", GpeNumber));
+ "Unable to disable GPE[0x%2X]", GpeNumber));
return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
}
@@ -865,28 +789,31 @@ AcpiEvGpeDispatch (
if (ACPI_FAILURE (Status))
{
ACPI_EXCEPTION ((AE_INFO, Status,
- "Unable to queue handler for GPE[%2X] - event disabled",
+ "Unable to queue handler for GPE[0x%2X] - event disabled",
GpeNumber));
}
break;
default:
- /* No handler or method to run! */
-
+ /*
+ * No handler or method to run!
+ * 03/2010: This case should no longer be possible. We will not allow
+ * a GPE to be enabled if it has no handler or method.
+ */
ACPI_ERROR ((AE_INFO,
- "No handler or method for GPE[%2X], disabling event",
+ "No handler or method for GPE[0x%2X], disabling event",
GpeNumber));
/*
- * Disable the GPE. The GPE will remain disabled until the ACPICA
- * Core Subsystem is restarted, or a handler is installed.
+ * Disable the GPE. The GPE will remain disabled a handler
+ * is installed or ACPICA is restarted.
*/
Status = AcpiEvDisableGpe (GpeEventInfo);
if (ACPI_FAILURE (Status))
{
ACPI_EXCEPTION ((AE_INFO, Status,
- "Unable to disable GPE[%2X]", GpeNumber));
+ "Unable to disable GPE[0x%2X]", GpeNumber));
return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
}
break;
OpenPOWER on IntegriCloud