ACPICA: Add additional module-level code support

This change will execute module-level code that is not at the
root of the namespace (under a Device object, etc.).
ACPICA BZ 762.

http://www.acpica.org/bugzilla/show_bug.cgi?id=762

Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
diff --git a/drivers/acpi/acpica/nseval.c b/drivers/acpi/acpica/nseval.c
index 846d113..f771e97 100644
--- a/drivers/acpi/acpica/nseval.c
+++ b/drivers/acpi/acpica/nseval.c
@@ -366,33 +366,49 @@
 acpi_ns_exec_module_code(union acpi_operand_object *method_obj,
 			 struct acpi_evaluate_info *info)
 {
-	union acpi_operand_object *root_obj;
+	union acpi_operand_object *parent_obj;
+	struct acpi_namespace_node *parent_node;
+	acpi_object_type type;
 	acpi_status status;
 
 	ACPI_FUNCTION_TRACE(ns_exec_module_code);
 
+	/*
+	 * Get the parent node. We cheat by using the next_object field
+	 * of the method object descriptor.
+	 */
+	parent_node = ACPI_CAST_PTR(struct acpi_namespace_node,
+				    method_obj->method.next_object);
+	type = acpi_ns_get_type(parent_node);
+
+	/* Must clear next_object (acpi_ns_attach_object needs the field) */
+
+	method_obj->method.next_object = NULL;
+
 	/* Initialize the evaluation information block */
 
 	ACPI_MEMSET(info, 0, sizeof(struct acpi_evaluate_info));
-	info->prefix_node = acpi_gbl_root_node;
+	info->prefix_node = parent_node;
 
 	/*
-	 * Get the currently attached root object. Add a reference, because the
+	 * Get the currently attached parent object. Add a reference, because the
 	 * ref count will be decreased when the method object is installed to
-	 * the root node.
+	 * the parent node.
 	 */
-	root_obj = acpi_ns_get_attached_object(acpi_gbl_root_node);
-	acpi_ut_add_reference(root_obj);
+	parent_obj = acpi_ns_get_attached_object(parent_node);
+	if (parent_obj) {
+		acpi_ut_add_reference(parent_obj);
+	}
 
-	/* Install the method (module-level code) in the root node */
+	/* Install the method (module-level code) in the parent node */
 
-	status = acpi_ns_attach_object(acpi_gbl_root_node, method_obj,
+	status = acpi_ns_attach_object(parent_node, method_obj,
 				       ACPI_TYPE_METHOD);
 	if (ACPI_FAILURE(status)) {
 		goto exit;
 	}
 
-	/* Execute the root node as a control method */
+	/* Execute the parent node as a control method */
 
 	status = acpi_ns_evaluate(info);
 
@@ -401,15 +417,19 @@
 
 	/* Detach the temporary method object */
 
-	acpi_ns_detach_object(acpi_gbl_root_node);
+	acpi_ns_detach_object(parent_node);
 
-	/* Restore the original root object */
+	/* Restore the original parent object */
 
-	status =
-	    acpi_ns_attach_object(acpi_gbl_root_node, root_obj,
-				  ACPI_TYPE_DEVICE);
+	if (parent_obj) {
+		status = acpi_ns_attach_object(parent_node, parent_obj, type);
+	} else {
+		parent_node->type = (u8)type;
+	}
 
       exit:
-	acpi_ut_remove_reference(root_obj);
+	if (parent_obj) {
+		acpi_ut_remove_reference(parent_obj);
+	}
 	return_VOID;
 }