summaryrefslogtreecommitdiffstats
path: root/sys/contrib/dev/acpica/nsinit.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/dev/acpica/nsinit.c')
-rw-r--r--sys/contrib/dev/acpica/nsinit.c337
1 files changed, 241 insertions, 96 deletions
diff --git a/sys/contrib/dev/acpica/nsinit.c b/sys/contrib/dev/acpica/nsinit.c
index 70a4d27..e06ccf7 100644
--- a/sys/contrib/dev/acpica/nsinit.c
+++ b/sys/contrib/dev/acpica/nsinit.c
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Module Name: nsinit - namespace initialization
- * $Revision: 1.68 $
+ * $Revision: 1.86 $
*
*****************************************************************************/
@@ -9,7 +9,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2005, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2007, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -141,6 +141,13 @@ AcpiNsInitOneDevice (
void *Context,
void **ReturnValue);
+static ACPI_STATUS
+AcpiNsFindIniMethods (
+ ACPI_HANDLE ObjHandle,
+ UINT32 NestingLevel,
+ void *Context,
+ void **ReturnValue);
+
/*******************************************************************************
*
@@ -163,7 +170,7 @@ AcpiNsInitializeObjects (
ACPI_INIT_WALK_INFO Info;
- ACPI_FUNCTION_TRACE ("NsInitializeObjects");
+ ACPI_FUNCTION_TRACE (NsInitializeObjects);
ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
@@ -182,8 +189,7 @@ AcpiNsInitializeObjects (
&Info, NULL);
if (ACPI_FAILURE (Status))
{
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "WalkNamespace failed! %s\n",
- AcpiFormatException (Status)));
+ ACPI_EXCEPTION ((AE_INFO, Status, "During WalkNamespace"));
}
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
@@ -226,7 +232,7 @@ AcpiNsInitializeDevices (
ACPI_DEVICE_WALK_INFO Info;
- ACPI_FUNCTION_TRACE ("NsInitializeDevices");
+ ACPI_FUNCTION_TRACE (NsInitializeDevices);
/* Init counters */
@@ -236,32 +242,47 @@ AcpiNsInitializeDevices (
Info.Num_INI = 0;
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
- "Executing all Device _STA and_INI methods:"));
+ "Initializing Device/Processor/Thermal objects by executing _INI methods:"));
+
+ /* Tree analysis: find all subtrees that contain _INI methods */
- Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
+ Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX, FALSE, AcpiNsFindIniMethods, &Info, NULL);
if (ACPI_FAILURE (Status))
{
- return_ACPI_STATUS (Status);
+ goto ErrorExit;
}
- /* Walk namespace for all objects */
+ /* Allocate the evaluation information block */
- Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX, TRUE, AcpiNsInitOneDevice, &Info, NULL);
+ Info.EvaluateInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
+ if (!Info.EvaluateInfo)
+ {
+ Status = AE_NO_MEMORY;
+ goto ErrorExit;
+ }
- (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
+ /* Walk namespace to execute all _INIs on present devices */
+ Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX, FALSE, AcpiNsInitOneDevice, &Info, NULL);
+
+ ACPI_FREE (Info.EvaluateInfo);
if (ACPI_FAILURE (Status))
{
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "WalkNamespace failed! %s\n",
- AcpiFormatException (Status)));
+ goto ErrorExit;
}
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
- "\n%hd Devices found containing: %hd _STA, %hd _INI methods\n",
- Info.DeviceCount, Info.Num_STA, Info.Num_INI));
+ "\nExecuted %hd _INI methods requiring %hd _STA executions (examined %hd objects)\n",
+ Info.Num_INI, Info.Num_STA, Info.DeviceCount));
return_ACPI_STATUS (Status);
+
+
+ErrorExit:
+ ACPI_EXCEPTION ((AE_INFO, Status, "During device initialization"));
+ return_ACPI_STATUS (Status);
}
@@ -293,13 +314,13 @@ AcpiNsInitOneObject (
void **ReturnValue)
{
ACPI_OBJECT_TYPE Type;
- ACPI_STATUS Status;
+ ACPI_STATUS Status = AE_OK;
ACPI_INIT_WALK_INFO *Info = (ACPI_INIT_WALK_INFO *) Context;
ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
ACPI_OPERAND_OBJECT *ObjDesc;
- ACPI_FUNCTION_NAME ("NsInitOneObject");
+ ACPI_FUNCTION_NAME (NsInitOneObject);
Info->ObjectCount++;
@@ -350,11 +371,7 @@ AcpiNsInitOneObject (
/*
* Must lock the interpreter before executing AML code
*/
- Status = AcpiExEnterInterpreter ();
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
+ AcpiExEnterInterpreter ();
/*
* Each of these types can contain executable AML code within the
@@ -393,11 +410,9 @@ AcpiNsInitOneObject (
if (ACPI_FAILURE (Status))
{
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_ERROR, "\n"));
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not execute arguments for [%4.4s] (%s), %s\n",
- AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Type),
- AcpiFormatException (Status)));
+ ACPI_EXCEPTION ((AE_INFO, Status,
+ "Could not execute arguments for [%4.4s] (%s)",
+ AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Type)));
}
/*
@@ -420,6 +435,80 @@ AcpiNsInitOneObject (
/*******************************************************************************
*
+ * FUNCTION: AcpiNsFindIniMethods
+ *
+ * PARAMETERS: ACPI_WALK_CALLBACK
+ *
+ * RETURN: ACPI_STATUS
+ *
+ * DESCRIPTION: Called during namespace walk. Finds objects named _INI under
+ * device/processor/thermal objects, and marks the entire subtree
+ * with a SUBTREE_HAS_INI flag. This flag is used during the
+ * subsequent device initialization walk to avoid entire subtrees
+ * that do not contain an _INI.
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+AcpiNsFindIniMethods (
+ ACPI_HANDLE ObjHandle,
+ UINT32 NestingLevel,
+ void *Context,
+ void **ReturnValue)
+{
+ ACPI_DEVICE_WALK_INFO *Info = ACPI_CAST_PTR (ACPI_DEVICE_WALK_INFO, Context);
+ ACPI_NAMESPACE_NODE *Node;
+ ACPI_NAMESPACE_NODE *ParentNode;
+
+
+ /* Keep count of device/processor/thermal objects */
+
+ Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle);
+ if ((Node->Type == ACPI_TYPE_DEVICE) ||
+ (Node->Type == ACPI_TYPE_PROCESSOR) ||
+ (Node->Type == ACPI_TYPE_THERMAL))
+ {
+ Info->DeviceCount++;
+ return (AE_OK);
+ }
+
+ /* We are only looking for methods named _INI */
+
+ if (!ACPI_COMPARE_NAME (Node->Name.Ascii, METHOD_NAME__INI))
+ {
+ return (AE_OK);
+ }
+
+ /*
+ * The only _INI methods that we care about are those that are
+ * present under Device, Processor, and Thermal objects.
+ */
+ ParentNode = AcpiNsGetParentNode (Node);
+ switch (ParentNode->Type)
+ {
+ case ACPI_TYPE_DEVICE:
+ case ACPI_TYPE_PROCESSOR:
+ case ACPI_TYPE_THERMAL:
+
+ /* Mark parent and bubble up the INI present flag to the root */
+
+ while (ParentNode)
+ {
+ ParentNode->Flags |= ANOBJ_SUBTREE_HAS_INI;
+ ParentNode = AcpiNsGetParentNode (ParentNode);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
* FUNCTION: AcpiNsInitOneDevice
*
* PARAMETERS: ACPI_WALK_CALLBACK
@@ -439,117 +528,173 @@ AcpiNsInitOneDevice (
void *Context,
void **ReturnValue)
{
- ACPI_DEVICE_WALK_INFO *Info = (ACPI_DEVICE_WALK_INFO *) Context;
- ACPI_PARAMETER_INFO Pinfo;
+ ACPI_DEVICE_WALK_INFO *WalkInfo = ACPI_CAST_PTR (ACPI_DEVICE_WALK_INFO, Context);
+ ACPI_EVALUATE_INFO *Info = WalkInfo->EvaluateInfo;
UINT32 Flags;
ACPI_STATUS Status;
+ ACPI_NAMESPACE_NODE *DeviceNode;
- ACPI_FUNCTION_TRACE ("NsInitOneDevice");
+ ACPI_FUNCTION_TRACE (NsInitOneDevice);
- Pinfo.Parameters = NULL;
- Pinfo.ParameterType = ACPI_PARAM_ARGS;
+ /* We are interested in Devices, Processors and ThermalZones only */
- Pinfo.Node = AcpiNsMapHandleToNode (ObjHandle);
- if (!Pinfo.Node)
+ DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle);
+ if ((DeviceNode->Type != ACPI_TYPE_DEVICE) &&
+ (DeviceNode->Type != ACPI_TYPE_PROCESSOR) &&
+ (DeviceNode->Type != ACPI_TYPE_THERMAL))
{
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS (AE_OK);
}
/*
- * We will run _STA/_INI on Devices, Processors and ThermalZones only
+ * Because of an earlier namespace analysis, all subtrees that contain an
+ * _INI method are tagged.
+ *
+ * If this device subtree does not contain any _INI methods, we
+ * can exit now and stop traversing this entire subtree.
*/
- if ((Pinfo.Node->Type != ACPI_TYPE_DEVICE) &&
- (Pinfo.Node->Type != ACPI_TYPE_PROCESSOR) &&
- (Pinfo.Node->Type != ACPI_TYPE_THERMAL))
+ if (!(DeviceNode->Flags & ANOBJ_SUBTREE_HAS_INI))
{
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS (AE_CTRL_DEPTH);
}
- if ((AcpiDbgLevel <= ACPI_LV_ALL_EXCEPTIONS) &&
- (!(AcpiDbgLevel & ACPI_LV_INFO)))
- {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "."));
- }
-
- Info->DeviceCount++;
-
/*
- * Run _STA to determine if we can run _INI on the device.
+ * Run _STA to determine if this device is present and functioning. We
+ * must know this information for two important reasons (from ACPI spec):
+ *
+ * 1) We can only run _INI if the device is present.
+ * 2) We must abort the device tree walk on this subtree if the device is
+ * not present and is not functional (we will not examine the children)
+ *
+ * The _STA method is not required to be present under the device, we
+ * assume the device is present if _STA does not exist.
*/
- ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD,
- Pinfo.Node, METHOD_NAME__STA));
- Status = AcpiUtExecute_STA (Pinfo.Node, &Flags);
+ ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (
+ ACPI_TYPE_METHOD, DeviceNode, METHOD_NAME__STA));
+ Status = AcpiUtExecute_STA (DeviceNode, &Flags);
if (ACPI_FAILURE (Status))
{
- if (Pinfo.Node->Type == ACPI_TYPE_DEVICE)
- {
- /* Ignore error and move on to next device */
+ /* Ignore error and move on to next device */
- return_ACPI_STATUS (AE_OK);
- }
+ return_ACPI_STATUS (AE_OK);
+ }
- /* _STA is not required for Processor or ThermalZone objects */
+ /*
+ * Flags == -1 means that _STA was not found. In this case, we assume that
+ * the device is both present and functional.
+ *
+ * From the ACPI spec, description of _STA:
+ *
+ * "If a device object (including the processor object) does not have an
+ * _STA object, then OSPM assumes that all of the above bits are set (in
+ * other words, the device is present, ..., and functioning)"
+ */
+ if (Flags != ACPI_UINT32_MAX)
+ {
+ WalkInfo->Num_STA++;
}
- else
+
+ /*
+ * Examine the PRESENT and FUNCTIONING status bits
+ *
+ * Note: ACPI spec does not seem to specify behavior for the present but
+ * not functioning case, so we assume functioning if present.
+ */
+ if (!(Flags & ACPI_STA_DEVICE_PRESENT))
{
- Info->Num_STA++;
+ /* Device is not present, we must examine the Functioning bit */
- if (!(Flags & 0x01))
+ if (Flags & ACPI_STA_DEVICE_FUNCTIONING)
{
- /* Don't look at children of a not present device */
-
- return_ACPI_STATUS(AE_CTRL_DEPTH);
+ /*
+ * Device is not present but is "functioning". In this case,
+ * we will not run _INI, but we continue to examine the children
+ * of this device.
+ *
+ * From the ACPI spec, description of _STA: (Note - no mention
+ * of whether to run _INI or not on the device in question)
+ *
+ * "_STA may return bit 0 clear (not present) with bit 3 set
+ * (device is functional). This case is used to indicate a valid
+ * device for which no device driver should be loaded (for example,
+ * a bridge device.) Children of this device may be present and
+ * valid. OSPM should continue enumeration below a device whose
+ * _STA returns this bit combination"
+ */
+ return_ACPI_STATUS (AE_OK);
+ }
+ else
+ {
+ /*
+ * Device is not present and is not functioning. We must abort the
+ * walk of this subtree immediately -- don't look at the children
+ * of such a device.
+ *
+ * From the ACPI spec, description of _INI:
+ *
+ * "If the _STA method indicates that the device is not present,
+ * OSPM will not run the _INI and will not examine the children
+ * of the device for _INI methods"
+ */
+ return_ACPI_STATUS (AE_CTRL_DEPTH);
}
}
/*
- * The device is present. Run _INI.
+ * The device is present or is assumed present if no _STA exists.
+ * Run the _INI if it exists (not required to exist)
+ *
+ * Note: We know there is an _INI within this subtree, but it may not be
+ * under this particular device, it may be lower in the branch.
*/
- ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD,
- Pinfo.Node, METHOD_NAME__INI));
- Status = AcpiNsEvaluateRelative (METHOD_NAME__INI, &Pinfo);
- if (ACPI_FAILURE (Status))
+ ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (
+ ACPI_TYPE_METHOD, DeviceNode, METHOD_NAME__INI));
+
+ Info->PrefixNode = DeviceNode;
+ Info->Pathname = METHOD_NAME__INI;
+ Info->Parameters = NULL;
+ Info->ParameterType = ACPI_PARAM_ARGS;
+ Info->Flags = ACPI_IGNORE_RETURN_VALUE;
+
+ Status = AcpiNsEvaluate (Info);
+ if (ACPI_SUCCESS (Status))
{
- /* No _INI (AE_NOT_FOUND) means device requires no initialization */
+ WalkInfo->Num_INI++;
- if (Status != AE_NOT_FOUND)
+ if ((AcpiDbgLevel <= ACPI_LV_ALL_EXCEPTIONS) &&
+ (!(AcpiDbgLevel & ACPI_LV_INFO)))
{
- /* Ignore error and move on to next device */
+ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "."));
+ }
+ }
#ifdef ACPI_DEBUG_OUTPUT
- char *ScopeName = AcpiNsGetExternalPathname (Pinfo.Node);
-
- ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "%s._INI failed: %s\n",
- ScopeName, AcpiFormatException (Status)));
+ else if (Status != AE_NOT_FOUND)
+ {
+ /* Ignore error and move on to next device */
- ACPI_MEM_FREE (ScopeName);
-#endif
- }
+ char *ScopeName = AcpiNsGetExternalPathname (Info->ResolvedNode);
- Status = AE_OK;
+ ACPI_EXCEPTION ((AE_INFO, Status, "during %s._INI execution",
+ ScopeName));
+ ACPI_FREE (ScopeName);
}
- else
- {
- /* Delete any return object (especially if ImplicitReturn is enabled) */
-
- if (Pinfo.ReturnObject)
- {
- AcpiUtRemoveReference (Pinfo.ReturnObject);
- }
+#endif
- /* Count of successful INIs */
+ /* Ignore errors from above */
- Info->Num_INI++;
- }
+ Status = AE_OK;
+ /*
+ * The _INI method has been run if present; call the Global Initialization
+ * Handler for this device.
+ */
if (AcpiGbl_InitHandler)
{
- /* External initialization handler is present, call it */
-
- Status = AcpiGbl_InitHandler (Pinfo.Node, ACPI_INIT_DEVICE_INI);
+ Status = AcpiGbl_InitHandler (DeviceNode, ACPI_INIT_DEVICE_INI);
}
return_ACPI_STATUS (Status);
OpenPOWER on IntegriCloud