summaryrefslogtreecommitdiff
path: root/source/components/namespace/nseval.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/components/namespace/nseval.c')
-rw-r--r--source/components/namespace/nseval.c71
1 files changed, 52 insertions, 19 deletions
diff --git a/source/components/namespace/nseval.c b/source/components/namespace/nseval.c
index a4819947dae40..33a45c03a7e1e 100644
--- a/source/components/namespace/nseval.c
+++ b/source/components/namespace/nseval.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2015, Intel Corp.
+ * Copyright (C) 2000 - 2016, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -418,7 +418,7 @@ AcpiNsExecModuleCodeList (
*
* DESCRIPTION: Execute a control method containing a block of module-level
* executable AML code. The control method is temporarily
- * installed to a local copy of the root node, then evaluated.
+ * installed to the root node, then evaluated.
*
******************************************************************************/
@@ -427,9 +427,10 @@ AcpiNsExecModuleCode (
ACPI_OPERAND_OBJECT *MethodObj,
ACPI_EVALUATE_INFO *Info)
{
- ACPI_STATUS Status;
- ACPI_NAMESPACE_NODE *TempNode;
+ ACPI_OPERAND_OBJECT *ParentObj;
ACPI_NAMESPACE_NODE *ParentNode;
+ ACPI_OBJECT_TYPE Type;
+ ACPI_STATUS Status;
ACPI_FUNCTION_TRACE (NsExecModuleCode);
@@ -439,20 +440,23 @@ AcpiNsExecModuleCode (
* Get the parent node. We cheat by using the NextObject field
* of the method object descriptor.
*/
- ParentNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE,
- MethodObj->Method.NextObject);
+ ParentNode = ACPI_CAST_PTR (
+ ACPI_NAMESPACE_NODE, MethodObj->Method.NextObject);
+ Type = AcpiNsGetType (ParentNode);
- /* Take a copy of the parent node to act as parent of this method */
-
- TempNode = ACPI_ALLOCATE (sizeof (ACPI_NAMESPACE_NODE));
- if (!TempNode)
+ /*
+ * Get the region handler and save it in the method object. We may need
+ * this if an operation region declaration causes a _REG method to be run.
+ *
+ * We can't do this in AcpiPsLinkModuleCode because
+ * AcpiGbl_RootNode->Object is NULL at PASS1.
+ */
+ if ((Type == ACPI_TYPE_DEVICE) && ParentNode->Object)
{
- return_VOID;
+ MethodObj->Method.Dispatch.Handler =
+ ParentNode->Object->Device.Handler;
}
- memcpy (TempNode, ParentNode, sizeof (ACPI_NAMESPACE_NODE));
- TempNode->Object = NULL; /* Clear the subobject */
-
/* Must clear NextObject (AcpiNsAttachObject needs the field) */
MethodObj->Method.NextObject = NULL;
@@ -460,14 +464,25 @@ AcpiNsExecModuleCode (
/* Initialize the evaluation information block */
memset (Info, 0, sizeof (ACPI_EVALUATE_INFO));
- Info->PrefixNode = TempNode;
+ Info->PrefixNode = ParentNode;
+
+ /*
+ * Get the currently attached parent object. Add a reference,
+ * because the ref count will be decreased when the method object
+ * is installed to the parent node.
+ */
+ ParentObj = AcpiNsGetAttachedObject (ParentNode);
+ if (ParentObj)
+ {
+ AcpiUtAddReference (ParentObj);
+ }
/* Install the method (module-level code) in the parent node */
- Status = AcpiNsAttachObject (TempNode, MethodObj, ACPI_TYPE_METHOD);
+ Status = AcpiNsAttachObject (ParentNode, MethodObj, ACPI_TYPE_METHOD);
if (ACPI_FAILURE (Status))
{
- goto Cleanup;
+ goto Exit;
}
/* Execute the parent node as a control method */
@@ -485,7 +500,25 @@ AcpiNsExecModuleCode (
AcpiUtRemoveReference (Info->ReturnObject);
}
-Cleanup:
- ACPI_FREE (TempNode);
+ /* Detach the temporary method object */
+
+ AcpiNsDetachObject (ParentNode);
+
+ /* Restore the original parent object */
+
+ if (ParentObj)
+ {
+ Status = AcpiNsAttachObject (ParentNode, ParentObj, Type);
+ }
+ else
+ {
+ ParentNode->Type = (UINT8) Type;
+ }
+
+Exit:
+ if (ParentObj)
+ {
+ AcpiUtRemoveReference (ParentObj);
+ }
return_VOID;
}