patch-2.4.23 linux-2.4.23/drivers/acpi/executer/exprep.c

Next file: linux-2.4.23/drivers/acpi/executer/exresnte.c
Previous file: linux-2.4.23/drivers/acpi/executer/exoparg1.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.22/drivers/acpi/executer/exprep.c linux-2.4.23/drivers/acpi/executer/exprep.c
@@ -53,6 +53,133 @@
 	 ACPI_MODULE_NAME    ("exprep")
 
 
+#ifdef ACPI_UNDER_DEVELOPMENT
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ex_generate_access
+ *
+ * PARAMETERS:  field_bit_offset    - Start of field within parent region/buffer
+ *              field_bit_length    - Length of field in bits
+ *              region_length       - Length of parent in bytes
+ *
+ * RETURN:      Field granularity (8, 16, 32 or 64) and
+ *              byte_alignment (1, 2, 3, or 4)
+ *
+ * DESCRIPTION: Generate an optimal access width for fields defined with the
+ *              any_acc keyword.
+ *
+ * NOTE: Need to have the region_length in order to check for boundary
+ *       conditions (end-of-region).  However, the region_length is a deferred
+ *       operation.  Therefore, to complete this implementation, the generation
+ *       of this access width must be deferred until the region length has
+ *       been evaluated.
+ *
+ ******************************************************************************/
+
+static u32
+acpi_ex_generate_access (
+	u32                             field_bit_offset,
+	u32                             field_bit_length,
+	u32                             region_length)
+{
+	u32                             field_byte_length;
+	u32                             field_byte_offset;
+	u32                             field_byte_end_offset;
+	u32                             access_byte_width;
+	u32                             field_start_offset;
+	u32                             field_end_offset;
+	u32                             minimum_access_width = 0xFFFFFFFF;
+	u32                             minimum_accesses = 0xFFFFFFFF;
+	u32                             accesses;
+
+
+	ACPI_FUNCTION_TRACE ("ex_generate_access");
+
+
+	/* Round Field start offset and length to "minimal" byte boundaries */
+
+	field_byte_offset  = ACPI_DIV_8 (ACPI_ROUND_DOWN (field_bit_offset, 8));
+	field_byte_end_offset = ACPI_DIV_8 (ACPI_ROUND_UP (field_bit_length + field_bit_offset, 8));
+	field_byte_length  = field_byte_end_offset - field_byte_offset;
+
+	ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
+			"Bit length %d, Bit offset %d\n",
+			field_bit_length, field_bit_offset));
+	ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
+			"Byte Length %d, Byte Offset %d, End Offset %d\n",
+			field_byte_length, field_byte_offset, field_byte_end_offset));
+
+	/*
+	 * Iterative search for the maximum access width that is both aligned
+	 * and does not go beyond the end of the region
+	 *
+	 * Start at byte_acc and work upwards to qword_acc max. (1,2,4,8 bytes)
+	 */
+	for (access_byte_width = 1; access_byte_width <= 8; access_byte_width <<= 1) {
+		/*
+		 * 1) Round end offset up to next access boundary and make sure that this
+		 *    does not go beyond the end of the parent region.
+		 * 2) When the Access width is greater than the field_byte_length, we are done.
+		 *    (This does not optimize for the perfectly aligned case yet).
+		 */
+		if (ACPI_ROUND_UP (field_byte_end_offset, access_byte_width) <= region_length) {
+			field_start_offset = ACPI_ROUND_DOWN (field_byte_offset, access_byte_width) /
+					  access_byte_width;
+			field_end_offset = ACPI_ROUND_UP   ((field_byte_length + field_byte_offset),
+					  access_byte_width) / access_byte_width;
+			accesses         = field_end_offset - field_start_offset;
+
+			ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
+					"access_width %d end is within region\n", access_byte_width));
+			ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
+					"Field Start %d, Field End %d -- requires %d accesses\n",
+					field_start_offset, field_end_offset, accesses));
+
+			/* Single access is optimal */
+
+			if (accesses <= 1) {
+				ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
+						"Entire field can be accessed with one operation of size %d\n",
+						access_byte_width));
+				return_VALUE (access_byte_width);
+			}
+
+			/*
+			 * Fits in the region, but requires more than one read/write.
+			 * try the next wider access on next iteration
+			 */
+			if (accesses < minimum_accesses) {
+				minimum_accesses   = accesses;
+				minimum_access_width = access_byte_width;
+			}
+		}
+		else {
+			ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
+					"access_width %d end is NOT within region\n", access_byte_width));
+			if (access_byte_width == 1) {
+				ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
+						"Field goes beyond end-of-region!\n"));
+				return_VALUE (0);     /* Field does not fit in the region at all */
+			}
+
+			/* This width goes beyond the end-of-region, back off to previous access */
+
+			ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
+					"Backing off to previous optimal access width of %d\n",
+					minimum_access_width));
+			return_VALUE (minimum_access_width);
+		}
+	}
+
+	/* Could not read/write field with one operation, just use max access width */
+
+	ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
+			"Cannot access field in one operation, using width 8\n"));
+	return_VALUE (8);
+}
+#endif /* ACPI_UNDER_DEVELOPMENT */
+
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ex_decode_field_access
@@ -74,12 +201,11 @@
 	u32                             *return_byte_alignment)
 {
 	u32                             access;
-	u8                              byte_alignment;
-	u8                              bit_length;
-/*    u32                             Length; */
+	u32                             byte_alignment;
+	u32                             bit_length;
 
 
-	ACPI_FUNCTION_NAME ("ex_decode_field_access");
+	ACPI_FUNCTION_TRACE ("ex_decode_field_access");
 
 
 	access = (field_flags & AML_FIELD_ACCESS_TYPE_MASK);
@@ -87,41 +213,15 @@
 	switch (access) {
 	case AML_FIELD_ACCESS_ANY:
 
+#ifdef ACPI_UNDER_DEVELOPMENT
+		byte_alignment = acpi_ex_generate_access (obj_desc->common_field.start_field_bit_offset,
+				 obj_desc->common_field.bit_length,
+				 0xFFFFFFFF /* Temp until we pass region_length as param */);
+		bit_length = byte_alignment * 8;
+#endif
+
 		byte_alignment = 1;
 		bit_length = 8;
-
-#if 0
-		/*
-		 * TBD: optimize
-		 *
-		 * Any attempt to optimize the access size to the size of the field
-		 * must take into consideration the length of the region and take
-		 * care that an access to the field will not attempt to access
-		 * beyond the end of the region.
-		 */
-
-		/* Use the length to set the access type */
-
-		length = obj_desc->common_field.bit_length;
-
-		if (length <= 8) {
-			bit_length = 8;
-		}
-		else if (length <= 16) {
-			bit_length = 16;
-		}
-		else if (length <= 32) {
-			bit_length = 32;
-		}
-		else if (length <= 64) {
-			bit_length = 64;
-		}
-		else {
-			/* Larger than Qword - just use byte-size chunks */
-
-			bit_length = 8;
-		}
-#endif
 		break;
 
 	case AML_FIELD_ACCESS_BYTE:
@@ -151,7 +251,7 @@
 		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
 			"Unknown field access type %X\n",
 			access));
-		return (0);
+		return_VALUE (0);
 	}
 
 	if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_BUFFER_FIELD) {
@@ -164,7 +264,7 @@
 	}
 
 	*return_byte_alignment = byte_alignment;
-	return (bit_length);
+	return_VALUE (bit_length);
 }
 
 
@@ -336,7 +436,7 @@
 		type = acpi_ns_get_type (info->region_node);
 		if (type != ACPI_TYPE_REGION) {
 			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
-				"Needed Region, found type %X %s\n",
+				"Needed Region, found type %X (%s)\n",
 				type, acpi_ut_get_type_name (type)));
 
 			return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
@@ -372,7 +472,7 @@
 		acpi_ut_add_reference (obj_desc->field.region_obj);
 
 		ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
-			"region_field: Bitoff=%X Off=%X Gran=%X Region %p\n",
+			"region_field: bit_off %X, Off %X, Gran %X, Region %p\n",
 			obj_desc->field.start_field_bit_offset, obj_desc->field.base_byte_offset,
 			obj_desc->field.access_byte_width, obj_desc->field.region_obj));
 		break;
@@ -390,7 +490,7 @@
 		acpi_ut_add_reference (obj_desc->bank_field.bank_obj);
 
 		ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
-			"Bank Field: bit_off=%X Off=%X Gran=%X Region %p bank_reg %p\n",
+			"Bank Field: bit_off %X, Off %X, Gran %X, Region %p, bank_reg %p\n",
 			obj_desc->bank_field.start_field_bit_offset,
 			obj_desc->bank_field.base_byte_offset,
 			obj_desc->field.access_byte_width,
@@ -417,9 +517,10 @@
 		acpi_ut_add_reference (obj_desc->index_field.index_obj);
 
 		ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
-			"index_field: bitoff=%X off=%X gran=%X Index %p Data %p\n",
+			"index_field: bit_off %X, Off %X, Value %X, Gran %X, Index %p, Data %p\n",
 			obj_desc->index_field.start_field_bit_offset,
 			obj_desc->index_field.base_byte_offset,
+			obj_desc->index_field.value,
 			obj_desc->field.access_byte_width,
 			obj_desc->index_field.index_obj,
 			obj_desc->index_field.data_obj));
@@ -437,7 +538,7 @@
 	status = acpi_ns_attach_object (info->field_node, obj_desc,
 			  acpi_ns_get_type (info->field_node));
 
-	ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "set named_obj %p (%4.4s) val = %p\n",
+	ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Set named_obj %p [%4.4s], obj_desc %p\n",
 			info->field_node, info->field_node->name.ascii, obj_desc));
 
 	/* Remove local reference to the object */

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)