Skip to content

Commit

Permalink
Namespace: Reorder \_SB._INI to make sure it is evaluated before _REG…
Browse files Browse the repository at this point in the history
… evaluations

This patch splits \_SB._INI evaluation from device initialization code, so
that it can be performed before PCI_Config _REG evaluations. This is
required for the device enumeration process. Some named objects are
initialized in \_SB._INI and PCI_Config _REG evaluations may use
uninitialized named objects because of the order issue.

This must be fixed before fixing ECDT order issue. There are existing
tables allowing ECDT EC to be used for the entire device enumeration
process, but the enabling of ECDT EC is done in \_SB._INI. Thus \_SB._INI
must be the first control method evaluated in the device enumeration
process. Normally, the order should be automatically ensured by the device
enumeration process itself (for example, PCI_Config _REGs are evaluated by
the PCI bus driver when the driver is probed by the enumeration process),
but since the process is split on Linux (partially done in Linux, partially
done in ACPICA), we need to ensure this with special logics in order to be
regression safe. Lv Zheng.

Signed-off-by: Lv Zheng <lv.zheng@intel.com>
  • Loading branch information
Lv Zheng committed Mar 18, 2016
1 parent c508f85 commit f005ee6
Showing 1 changed file with 52 additions and 20 deletions.
72 changes: 52 additions & 20 deletions source/components/namespace/nsinit.c
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ AcpiNsInitializeDevices (
{
ACPI_STATUS Status = AE_OK;
ACPI_DEVICE_WALK_INFO Info;
ACPI_HANDLE Handle;


ACPI_FUNCTION_TRACE (NsInitializeDevices);
Expand Down Expand Up @@ -283,6 +284,27 @@ AcpiNsInitializeDevices (
{
Info.Num_INI++;
}

/*
* Execute \_SB._INI.
* There appears to be a strict order requirement for \_SB._INI,
* which should be evaluated before any _REG evaluations.
*/
Status = AcpiGetHandle (NULL, "\\_SB", &Handle);
if (ACPI_SUCCESS (Status))
{
memset (Info.EvaluateInfo, 0, sizeof (ACPI_EVALUATE_INFO));
Info.EvaluateInfo->PrefixNode = Handle;
Info.EvaluateInfo->RelativePathname = METHOD_NAME__INI;
Info.EvaluateInfo->Parameters = NULL;
Info.EvaluateInfo->Flags = ACPI_IGNORE_RETURN_VALUE;

Status = AcpiNsEvaluate (Info.EvaluateInfo);
if (ACPI_SUCCESS (Status))
{
Info.Num_INI++;
}
}
}

/*
Expand All @@ -291,6 +313,12 @@ AcpiNsInitializeDevices (
* Note: Any objects accessed by the _REG methods will be automatically
* initialized, even if they contain executable AML (see the call to
* AcpiNsInitializeObjects below).
*
* Note: According to the ACPI specification, we actually needn't execute
* _REG for SystemMemory/SystemIo operation regions, but for PCI_Config
* operation regions, it is required to evaluate _REG for those on a PCI
* root bus that doesn't contain _BBN object. So this code is kept here
* in order not to break things.
*/
if (!(Flags & ACPI_NO_ADDRESS_SPACE_INIT))
{
Expand Down Expand Up @@ -714,33 +742,37 @@ AcpiNsInitOneDevice (
* 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, DeviceNode, METHOD_NAME__INI));
if (!ACPI_COMPARE_NAME (DeviceNode->Name.Ascii, "_SB_") ||
DeviceNode->Parent != AcpiGbl_RootNode)
{
ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (
ACPI_TYPE_METHOD, DeviceNode, METHOD_NAME__INI));

memset (Info, 0, sizeof (ACPI_EVALUATE_INFO));
Info->PrefixNode = DeviceNode;
Info->RelativePathname = METHOD_NAME__INI;
Info->Parameters = NULL;
Info->Flags = ACPI_IGNORE_RETURN_VALUE;
memset (Info, 0, sizeof (ACPI_EVALUATE_INFO));
Info->PrefixNode = DeviceNode;
Info->RelativePathname = METHOD_NAME__INI;
Info->Parameters = NULL;
Info->Flags = ACPI_IGNORE_RETURN_VALUE;

Status = AcpiNsEvaluate (Info);
if (ACPI_SUCCESS (Status))
{
WalkInfo->Num_INI++;
}
Status = AcpiNsEvaluate (Info);
if (ACPI_SUCCESS (Status))
{
WalkInfo->Num_INI++;
}

#ifdef ACPI_DEBUG_OUTPUT
else if (Status != AE_NOT_FOUND)
{
/* Ignore error and move on to next device */
else if (Status != AE_NOT_FOUND)
{
/* Ignore error and move on to next device */

char *ScopeName = AcpiNsGetNormalizedPathname (DeviceNode, TRUE);
char *ScopeName = AcpiNsGetNormalizedPathname (DeviceNode, TRUE);

ACPI_EXCEPTION ((AE_INFO, Status, "during %s._INI execution",
ScopeName));
ACPI_FREE (ScopeName);
}
ACPI_EXCEPTION ((AE_INFO, Status, "during %s._INI execution",
ScopeName));
ACPI_FREE (ScopeName);
}
#endif
}

/* Ignore errors from above */

Expand Down

0 comments on commit f005ee6

Please sign in to comment.