Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 89877e42827f16fa5f86b1df0c2860b1 > files > 86

kernel-2.6.18-128.1.10.el5.src.rpm

From: Luming Yu <luyu@redhat.com>
Date: Thu, 9 Aug 2007 15:40:07 +0800
Subject: [acpi] Support external package objs as method args
Message-id: 46BAC4D7.1080104@redhat.com
O-Subject: [RHEL 5.1 PATCH] bz 223290 ACPI CA version update; Support for external package objects as method arguments
Bugzilla: 241899

bz 223290

Description of problem:

ACPICA: Support for external package objects as method arguments
Implemented support to allow Package objects to be passed as
method arguments to the acpi_evaluate_object interface. Previously,
this would return an AE_NOT_IMPLEMENTED exception.

Upstream status:
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=6287ee32952b502c23d54f12895c3895ddbe5013

The back port of the external package patch has passed through my
regression test on my tiger4.
Please do further test on HP and other platforms.
Please review, test and ACK.

Thanks,
LUming

Acked-by: Brian Maly <bmaly@redhat.com>

diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c
index 5e1a80d..e2a11ca 100644
--- a/drivers/acpi/utilities/utcopy.c
+++ b/drivers/acpi/utilities/utcopy.c
@@ -68,6 +68,10 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *user_obj,
 				union acpi_operand_object **return_obj);
 
 static acpi_status
+acpi_ut_copy_epackage_to_ipackage(union acpi_object *external_object,
+				  union acpi_operand_object **internal_object);
+
+static acpi_status
 acpi_ut_copy_simple_object(union acpi_operand_object *source_desc,
 			   union acpi_operand_object *dest_desc);
 
@@ -518,77 +522,73 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object,
 	return_ACPI_STATUS(AE_NO_MEMORY);
 }
 
-#ifdef ACPI_FUTURE_IMPLEMENTATION
-/* Code to convert packages that are parameters to control methods */
-
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ut_copy_epackage_to_ipackage
  *
- * PARAMETERS:  *internal_object   - Pointer to the object we are returning
- *              *Buffer            - Where the object is returned
- *              *space_used        - Where the length of the object is returned
+ * PARAMETERS:  external_object     - The external object to be converted
+ *              internal_object     - Where the internal object is returned
  *
  * RETURN:      Status
  *
- * DESCRIPTION: This function is called to place a package object in a user
- *              buffer.  A package object by definition contains other objects.
- *
- *              The buffer is assumed to have sufficient space for the object.
- *              The caller must have verified the buffer length needed using the
- *              acpi_ut_get_object_size function before calling this function.
+ * DESCRIPTION: Copy an external package object to an internal package.
+ *              Handles nested packages.
  *
  ******************************************************************************/
 
 static acpi_status
-acpi_ut_copy_epackage_to_ipackage(union acpi_operand_object *internal_object,
-				  u8 * buffer, u32 * space_used)
+acpi_ut_copy_epackage_to_ipackage(union acpi_object *external_object,
+				  union acpi_operand_object **internal_object)
 {
-	u8 *free_space;
-	union acpi_object *external_object;
-	u32 length = 0;
-	u32 this_index;
-	u32 object_space = 0;
-	union acpi_operand_object *this_internal_obj;
-	union acpi_object *this_external_obj;
+	acpi_status status = AE_OK;
+	union acpi_operand_object *package_object;
+	union acpi_operand_object **package_elements;
+	acpi_native_uint i;
 
 	ACPI_FUNCTION_TRACE(ut_copy_epackage_to_ipackage);
 
-	/*
-	 * First package at head of the buffer
-	 */
-	external_object = (union acpi_object *)buffer;
+	/* Create the package object */
 
-	/*
-	 * Free space begins right after the first package
-	 */
-	free_space = buffer + sizeof(union acpi_object);
+	package_object =
+	    acpi_ut_create_package_object(external_object->package.count);
+	if (!package_object) {
+		return_ACPI_STATUS(AE_NO_MEMORY);
+	}
 
-	external_object->type = ACPI_GET_OBJECT_TYPE(internal_object);
-	external_object->package.count = internal_object->package.count;
-	external_object->package.elements = (union acpi_object *)free_space;
+	package_elements = package_object->package.elements;
 
 	/*
-	 * Build an array of ACPI_OBJECTS in the buffer
-	 * and move the free space past it
+	 * Recursive implementation. Probably ok, since nested external packages
+	 * as parameters should be very rare.
 	 */
-	free_space +=
-	    external_object->package.count * sizeof(union acpi_object);
+	for (i = 0; i < external_object->package.count; i++) {
+		status =
+		    acpi_ut_copy_eobject_to_iobject(&external_object->package.
+						    elements[i],
+						    &package_elements[i]);
+		if (ACPI_FAILURE(status)) {
 
-	/* Call walk_package */
+			/* Truncate package and delete it */
 
-}
+			package_object->package.count = i;
+			package_elements[i] = NULL;
+			acpi_ut_remove_reference(package_object);
+			return_ACPI_STATUS(status);
+		}
+	}
 
-#endif				/* Future implementation */
+	*internal_object = package_object;
+	return_ACPI_STATUS(status);
+}
 
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ut_copy_eobject_to_iobject
  *
- * PARAMETERS:  *internal_object   - The external object to be converted
- *              *buffer_ptr     - Where the internal object is returned
+ * PARAMETERS:  external_object     - The external object to be converted
+ *              internal_object     - Where the internal object is returned
  *
- * RETURN:      Status          - the status of the call
+ * RETURN:      Status              - the status of the call
  *
  * DESCRIPTION: Converts an external object to an internal object.
  *
@@ -603,16 +603,10 @@ acpi_ut_copy_eobject_to_iobject(union acpi_object *external_object,
 	ACPI_FUNCTION_TRACE(ut_copy_eobject_to_iobject);
 
 	if (external_object->type == ACPI_TYPE_PACKAGE) {
-		/*
-		 * Packages as external input to control methods are not supported,
-		 */
-		ACPI_ERROR((AE_INFO,
-			    "Packages as parameters not implemented!"));
-
-		return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
-	}
-
-	else {
+		status =
+		    acpi_ut_copy_epackage_to_ipackage(external_object,
+						      internal_object);
+	} else {
 		/*
 		 * Build a simple object (no nested objects)
 		 */
@@ -794,24 +788,14 @@ acpi_ut_copy_ielement_to_ielement(u8 object_type,
 		 * Create and build the package object
 		 */
 		target_object =
-		    acpi_ut_create_internal_object(ACPI_TYPE_PACKAGE);
+		    acpi_ut_create_package_object(source_object->package.count);
 		if (!target_object) {
 			return (AE_NO_MEMORY);
 		}
 
-		target_object->package.count = source_object->package.count;
 		target_object->common.flags = source_object->common.flags;
 
 		/*
-		 * Create the object array
-		 */
-		target_object->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size) source_object->package.count + 1) * sizeof(void *));
-		if (!target_object->package.elements) {
-			status = AE_NO_MEMORY;
-			goto error_exit;
-		}
-
-		/*
 		 * Pass the new package object back to the package walk routine
 		 */
 		state->pkg.this_target_obj = target_object;
diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c
index ba7d8ac..46beb8a 100644
--- a/drivers/acpi/utilities/utobject.c
+++ b/drivers/acpi/utilities/utobject.c
@@ -146,6 +146,48 @@ union acpi_operand_object *acpi_ut_create_internal_object_dbg(char *module_name,
 
 /*******************************************************************************
  *
+ * FUNCTION:    acpi_ut_create_package_object
+ *
+ * PARAMETERS:  Count               - Number of package elements
+ *
+ * RETURN:      Pointer to a new Package object, null on failure
+ *
+ * DESCRIPTION: Create a fully initialized package object
+ *
+ ******************************************************************************/
+
+union acpi_operand_object *acpi_ut_create_package_object(u32 count)
+{
+	union acpi_operand_object *package_desc;
+	union acpi_operand_object **package_elements;
+
+	ACPI_FUNCTION_TRACE_U32(ut_create_package_object, count);
+
+	/* Create a new Package object */
+
+	package_desc = acpi_ut_create_internal_object(ACPI_TYPE_PACKAGE);
+	if (!package_desc) {
+		return_PTR(NULL);
+	}
+
+	/*
+	 * Create the element array. Count+1 allows the array to be null
+	 * terminated.
+	 */
+	package_elements = ACPI_ALLOCATE_ZEROED((acpi_size)
+						(count + 1) * sizeof(void *));
+	if (!package_elements) {
+		ACPI_FREE(package_desc);
+		return_PTR(NULL);
+	}
+
+	package_desc->package.count = count;
+	package_desc->package.elements = package_elements;
+	return_PTR(package_desc);
+}
+
+/*******************************************************************************
+ *
  * FUNCTION:    acpi_ut_create_buffer_object
  *
  * PARAMETERS:  buffer_size            - Size of buffer to be created
diff --git a/include/acpi/acutils.h b/include/acpi/acutils.h
index ba039ea..383ce92 100644
--- a/include/acpi/acutils.h
+++ b/include/acpi/acutils.h
@@ -392,6 +392,8 @@ void acpi_ut_delete_object_desc(union acpi_operand_object *object);
 
 u8 acpi_ut_valid_internal_object(void *object);
 
+union acpi_operand_object *acpi_ut_create_package_object(u32 count);
+
 union acpi_operand_object *acpi_ut_create_buffer_object(acpi_size buffer_size);
 
 union acpi_operand_object *acpi_ut_create_string_object(acpi_size string_size);