diff options
Diffstat (limited to 'events/evgpeinit.c')
-rw-r--r-- | events/evgpeinit.c | 285 |
1 files changed, 27 insertions, 258 deletions
diff --git a/events/evgpeinit.c b/events/evgpeinit.c index be38f0c..b46b91a 100644 --- a/events/evgpeinit.c +++ b/events/evgpeinit.c @@ -118,12 +118,28 @@ #include "accommon.h" #include "acevents.h" #include "acnamesp.h" -#include "acinterp.h" #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME ("evgpeinit") +/* + * Note: History of _PRW support in ACPICA + * + * Originally (2000 - 2010), the GPE initialization code performed a walk of + * the entire namespace to execute the _PRW methods and detect all GPEs + * capable of waking the system. + * + * As of 10/2010, the _PRW method execution has been removed since it is + * actually unnecessary. The host OS must in fact execute all _PRW methods + * in order to identify the device/power-resource dependencies. We now put + * the onus on the host OS to identify the wake GPEs as part of this process + * and to inform ACPICA of these GPEs via the AcpiSetupGpeForWake interface. This + * not only reduces the complexity of the ACPICA initialization code, but in + * some cases (on systems with very large namespaces) it should reduce the + * kernel boot time as well. + */ + /******************************************************************************* * * FUNCTION: AcpiEvGpeInitialize @@ -288,10 +304,7 @@ Cleanup: * * DESCRIPTION: Check for new GPE methods (_Lxx/_Exx) made available as a * result of a Load() or LoadTable() operation. If new GPE - * methods have been installed, register the new methods and - * enable and runtime GPEs that are associated with them. Also, - * run any newly loaded _PRW methods in order to discover any - * new CAN_WAKE GPEs. + * methods have been installed, register the new methods. * ******************************************************************************/ @@ -303,49 +316,13 @@ AcpiEvUpdateGpes ( ACPI_GPE_BLOCK_INFO *GpeBlock; ACPI_GPE_WALK_INFO WalkInfo; ACPI_STATUS Status = AE_OK; - UINT32 NewWakeGpeCount = 0; - - - /* We will examine only _PRW/_Lxx/_Exx methods owned by this table */ - - WalkInfo.OwnerId = TableOwnerId; - WalkInfo.ExecuteByOwnerId = TRUE; - WalkInfo.Count = 0; - if (AcpiGbl_LeaveWakeGpesDisabled) - { - /* - * 1) Run any newly-loaded _PRW methods to find any GPEs that - * can now be marked as CAN_WAKE GPEs. Note: We must run the - * _PRW methods before we process the _Lxx/_Exx methods because - * we will enable all runtime GPEs associated with the new - * _Lxx/_Exx methods at the time we process those methods. - * - * Unlock interpreter so that we can run the _PRW methods. - */ - WalkInfo.GpeBlock = NULL; - WalkInfo.GpeDevice = NULL; - - AcpiExExitInterpreter (); - - Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, - AcpiEvMatchPrwAndGpe, NULL, &WalkInfo, NULL); - if (ACPI_FAILURE (Status)) - { - ACPI_EXCEPTION ((AE_INFO, Status, - "While executing _PRW methods")); - } - - AcpiExEnterInterpreter (); - NewWakeGpeCount = WalkInfo.Count; - } /* - * 2) Find any _Lxx/_Exx GPE methods that have just been loaded. + * Find any _Lxx/_Exx GPE methods that have just been loaded. * - * Any GPEs that correspond to new _Lxx/_Exx methods and are not - * marked as CAN_WAKE are immediately enabled. + * Any GPEs that correspond to new _Lxx/_Exx methods are immediately + * enabled. * * Examine the namespace underneath each GpeDevice within the * GpeBlock lists. @@ -357,7 +334,8 @@ AcpiEvUpdateGpes ( } WalkInfo.Count = 0; - WalkInfo.EnableThisGpe = TRUE; + WalkInfo.OwnerId = TableOwnerId; + WalkInfo.ExecuteByOwnerId = TRUE; /* Walk the interrupt level descriptor list */ @@ -388,11 +366,9 @@ AcpiEvUpdateGpes ( GpeXruptInfo = GpeXruptInfo->Next; } - if (WalkInfo.Count || NewWakeGpeCount) + if (WalkInfo.Count) { - ACPI_INFO ((AE_INFO, - "Enabled %u new runtime GPEs, added %u new wakeup GPEs", - WalkInfo.Count, NewWakeGpeCount)); + ACPI_INFO ((AE_INFO, "Enabled %u new GPEs", WalkInfo.Count)); } (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); @@ -422,9 +398,7 @@ AcpiEvUpdateGpes ( * xx - is the GPE number [in HEX] * * If WalkInfo->ExecuteByOwnerId is TRUE, we only execute examine GPE methods - * with that owner. - * If WalkInfo->EnableThisGpe is TRUE, the GPE that is referred to by a GPE - * method is immediately enabled (Used for Load/LoadTable operators) + * with that owner. * ******************************************************************************/ @@ -438,8 +412,6 @@ AcpiEvMatchGpeMethod ( ACPI_NAMESPACE_NODE *MethodNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle); ACPI_GPE_WALK_INFO *WalkInfo = ACPI_CAST_PTR (ACPI_GPE_WALK_INFO, Context); ACPI_GPE_EVENT_INFO *GpeEventInfo; - ACPI_NAMESPACE_NODE *GpeDevice; - ACPI_STATUS Status; UINT32 GpeNumber; char Name[ACPI_NAME_SIZE + 1]; UINT8 Type; @@ -474,9 +446,6 @@ AcpiEvMatchGpeMethod ( /* * 3) Edge/Level determination is based on the 2nd character * of the method name - * - * NOTE: Default GPE type is RUNTIME only. Later, if a _PRW object is - * found that points to this GPE, the ACPI_GPE_CAN_WAKE flag is set. */ switch (Name[1]) { @@ -551,212 +520,12 @@ AcpiEvMatchGpeMethod ( * Add the GPE information from above to the GpeEventInfo block for * use during dispatch of this GPE. */ + GpeEventInfo->Flags &= ~(ACPI_GPE_DISPATCH_MASK); GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_METHOD); GpeEventInfo->Dispatch.MethodNode = MethodNode; - /* - * Enable this GPE if requested. This only happens when during the - * execution of a Load or LoadTable operator. We have found a new - * GPE method and want to immediately enable the GPE if it is a - * runtime GPE. - */ - if (WalkInfo->EnableThisGpe) - { - /* Ignore GPEs that can wake the system */ - - if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE) || - !AcpiGbl_LeaveWakeGpesDisabled) - { - WalkInfo->Count++; - GpeDevice = WalkInfo->GpeDevice; - - if (GpeDevice == AcpiGbl_FadtGpeDevice) - { - GpeDevice = NULL; - } - - Status = AcpiEnableGpe (GpeDevice, GpeNumber); - if (ACPI_FAILURE (Status)) - { - ACPI_EXCEPTION ((AE_INFO, Status, - "Could not enable GPE 0x%02X", GpeNumber)); - } - } - } - ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Registered GPE method %s as GPE number 0x%.2X\n", Name, GpeNumber)); return_ACPI_STATUS (AE_OK); } - - -/******************************************************************************* - * - * FUNCTION: AcpiEvMatchPrwAndGpe - * - * PARAMETERS: Callback from WalkNamespace - * - * RETURN: Status. NOTE: We ignore errors so that the _PRW walk is - * not aborted on a single _PRW failure. - * - * DESCRIPTION: Called from AcpiWalkNamespace. Expects each object to be a - * Device. Run the _PRW method. If present, extract the GPE - * number and mark the GPE as a CAN_WAKE GPE. Allows a - * per-OwnerId execution if ExecuteByOwnerId is TRUE in the - * WalkInfo parameter block. - * - * If WalkInfo->ExecuteByOwnerId is TRUE, we only execute _PRWs with that - * owner. - * If WalkInfo->GpeDevice is NULL, we execute every _PRW found. Otherwise, - * we only execute _PRWs that refer to the input GpeDevice. - * - ******************************************************************************/ - -ACPI_STATUS -AcpiEvMatchPrwAndGpe ( - ACPI_HANDLE ObjHandle, - UINT32 Level, - void *Context, - void **ReturnValue) -{ - ACPI_GPE_WALK_INFO *WalkInfo = ACPI_CAST_PTR (ACPI_GPE_WALK_INFO, Context); - ACPI_NAMESPACE_NODE *GpeDevice; - ACPI_GPE_BLOCK_INFO *GpeBlock; - ACPI_NAMESPACE_NODE *TargetGpeDevice; - ACPI_NAMESPACE_NODE *PrwNode; - ACPI_GPE_EVENT_INFO *GpeEventInfo; - ACPI_OPERAND_OBJECT *PkgDesc; - ACPI_OPERAND_OBJECT *ObjDesc; - UINT32 GpeNumber; - ACPI_STATUS Status; - - - ACPI_FUNCTION_TRACE (EvMatchPrwAndGpe); - - - /* Check for a _PRW method under this device */ - - Status = AcpiNsGetNode (ObjHandle, METHOD_NAME__PRW, - ACPI_NS_NO_UPSEARCH, &PrwNode); - if (ACPI_FAILURE (Status)) - { - return_ACPI_STATUS (AE_OK); - } - - /* Check if requested OwnerId matches this OwnerId */ - - if ((WalkInfo->ExecuteByOwnerId) && - (PrwNode->OwnerId != WalkInfo->OwnerId)) - { - return_ACPI_STATUS (AE_OK); - } - - /* Execute the _PRW */ - - Status = AcpiUtEvaluateObject (PrwNode, NULL, - ACPI_BTYPE_PACKAGE, &PkgDesc); - if (ACPI_FAILURE (Status)) - { - return_ACPI_STATUS (AE_OK); - } - - /* The returned _PRW package must have at least two elements */ - - if (PkgDesc->Package.Count < 2) - { - goto Cleanup; - } - - /* Extract pointers from the input context */ - - GpeDevice = WalkInfo->GpeDevice; - GpeBlock = WalkInfo->GpeBlock; - - /* - * The _PRW object must return a package, we are only interested - * in the first element - */ - ObjDesc = PkgDesc->Package.Elements[0]; - - if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER) - { - /* Use FADT-defined GPE device (from definition of _PRW) */ - - TargetGpeDevice = NULL; - if (GpeDevice) - { - TargetGpeDevice = AcpiGbl_FadtGpeDevice; - } - - /* Integer is the GPE number in the FADT described GPE blocks */ - - GpeNumber = (UINT32) ObjDesc->Integer.Value; - } - else if (ObjDesc->Common.Type == ACPI_TYPE_PACKAGE) - { - /* Package contains a GPE reference and GPE number within a GPE block */ - - if ((ObjDesc->Package.Count < 2) || - ((ObjDesc->Package.Elements[0])->Common.Type != - ACPI_TYPE_LOCAL_REFERENCE) || - ((ObjDesc->Package.Elements[1])->Common.Type != - ACPI_TYPE_INTEGER)) - { - goto Cleanup; - } - - /* Get GPE block reference and decode */ - - TargetGpeDevice = ObjDesc->Package.Elements[0]->Reference.Node; - GpeNumber = (UINT32) ObjDesc->Package.Elements[1]->Integer.Value; - } - else - { - /* Unknown type, just ignore it */ - - goto Cleanup; - } - - /* Get the GpeEventInfo for this GPE */ - - if (GpeDevice) - { - /* - * Is this GPE within this block? - * - * TRUE if and only if these conditions are true: - * 1) The GPE devices match. - * 2) The GPE index(number) is within the range of the Gpe Block - * associated with the GPE device. - */ - if (GpeDevice != TargetGpeDevice) - { - goto Cleanup; - } - - GpeEventInfo = AcpiEvLowGetGpeInfo (GpeNumber, GpeBlock); - } - else - { - /* GpeDevice is NULL, just match the TargetDevice and GpeNumber */ - - GpeEventInfo = AcpiEvGetGpeEventInfo (TargetGpeDevice, GpeNumber); - } - - if (GpeEventInfo) - { - if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE)) - { - /* This GPE can wake the system */ - - GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE; - WalkInfo->Count++; - } - } - -Cleanup: - AcpiUtRemoveReference (PkgDesc); - return_ACPI_STATUS (AE_OK); -} - |