ACPICA: Revert "Revert "Enable multi-byte EC transfers

This reverts commit f23b9c7(http://git.moblin.org/cgit.cgi/acpica/commit/?id=f23b9c7)
The problem with this change was determined to be a problem with
the FreeBSD host OSL (OS services layer), not with this patch
itself. Therefore, re-introducing this change into the main ACPICA
code. See ACPICA bugzilla 863.

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

Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
diff --git a/drivers/acpi/acpica/exfldio.c b/drivers/acpi/acpica/exfldio.c
index 0472173..38293fd 100644
--- a/drivers/acpi/acpica/exfldio.c
+++ b/drivers/acpi/acpica/exfldio.c
@@ -119,8 +119,8 @@
 	}
 
 	/*
-	 * Exit now for SMBus or IPMI address space, it has a non-linear address space
-	 * and the request cannot be directly validated
+	 * Exit now for SMBus or IPMI address space, it has a non-linear
+	 * address space and the request cannot be directly validated
 	 */
 	if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS ||
 	    rgn_desc->region.space_id == ACPI_ADR_SPACE_IPMI) {
@@ -147,8 +147,7 @@
 	 * (Region length is specified in bytes)
 	 */
 	if (rgn_desc->region.length <
-	    (obj_desc->common_field.base_byte_offset +
-	     field_datum_byte_offset +
+	    (obj_desc->common_field.base_byte_offset + field_datum_byte_offset +
 	     obj_desc->common_field.access_byte_width)) {
 		if (acpi_gbl_enable_interpreter_slack) {
 			/*
@@ -680,6 +679,7 @@
 	u32 buffer_tail_bits;
 	u32 datum_count;
 	u32 field_datum_count;
+	u32 access_bit_width;
 	u32 i;
 
 	ACPI_FUNCTION_TRACE(ex_extract_from_field);
@@ -694,16 +694,36 @@
 
 		return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
 	}
+
 	ACPI_MEMSET(buffer, 0, buffer_length);
+	access_bit_width = ACPI_MUL_8(obj_desc->common_field.access_byte_width);
+
+	/* Handle the simple case here */
+
+	if ((obj_desc->common_field.start_field_bit_offset == 0) &&
+	    (obj_desc->common_field.bit_length == access_bit_width)) {
+		status = acpi_ex_field_datum_io(obj_desc, 0, buffer, ACPI_READ);
+		return_ACPI_STATUS(status);
+	}
+
+/* TBD: Move to common setup code */
+
+	/* Field algorithm is limited to sizeof(u64), truncate if needed */
+
+	if (obj_desc->common_field.access_byte_width > sizeof(u64)) {
+		obj_desc->common_field.access_byte_width = sizeof(u64);
+		access_bit_width = sizeof(u64) * 8;
+	}
 
 	/* Compute the number of datums (access width data items) */
 
-	datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
-				       obj_desc->common_field.access_bit_width);
+	datum_count =
+	    ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
+			     access_bit_width);
+
 	field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
 					     obj_desc->common_field.
 					     start_field_bit_offset,
-					     obj_desc->common_field.
 					     access_bit_width);
 
 	/* Priming read from the field */
@@ -738,12 +758,11 @@
 		 * This avoids the differences in behavior between different compilers
 		 * concerning shift values larger than the target data width.
 		 */
-		if ((obj_desc->common_field.access_bit_width -
-		     obj_desc->common_field.start_field_bit_offset) <
+		if (access_bit_width -
+		    obj_desc->common_field.start_field_bit_offset <
 		    ACPI_INTEGER_BIT_SIZE) {
 			merged_datum |=
-			    raw_datum << (obj_desc->common_field.
-					  access_bit_width -
+			    raw_datum << (access_bit_width -
 					  obj_desc->common_field.
 					  start_field_bit_offset);
 		}
@@ -765,8 +784,7 @@
 
 	/* Mask off any extra bits in the last datum */
 
-	buffer_tail_bits = obj_desc->common_field.bit_length %
-	    obj_desc->common_field.access_bit_width;
+	buffer_tail_bits = obj_desc->common_field.bit_length % access_bit_width;
 	if (buffer_tail_bits) {
 		merged_datum &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits);
 	}
@@ -798,6 +816,7 @@
 acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
 			  void *buffer, u32 buffer_length)
 {
+	void *new_buffer;
 	acpi_status status;
 	u64 mask;
 	u64 width_mask;
@@ -808,9 +827,9 @@
 	u32 buffer_tail_bits;
 	u32 datum_count;
 	u32 field_datum_count;
-	u32 i;
+	u32 access_bit_width;
 	u32 required_length;
-	void *new_buffer;
+	u32 i;
 
 	ACPI_FUNCTION_TRACE(ex_insert_into_field);
 
@@ -844,17 +863,24 @@
 		buffer_length = required_length;
 	}
 
+/* TBD: Move to common setup code */
+
+	/* Algo is limited to sizeof(u64), so cut the access_byte_width */
+	if (obj_desc->common_field.access_byte_width > sizeof(u64)) {
+		obj_desc->common_field.access_byte_width = sizeof(u64);
+	}
+
+	access_bit_width = ACPI_MUL_8(obj_desc->common_field.access_byte_width);
+
 	/*
 	 * Create the bitmasks used for bit insertion.
 	 * Note: This if/else is used to bypass compiler differences with the
 	 * shift operator
 	 */
-	if (obj_desc->common_field.access_bit_width == ACPI_INTEGER_BIT_SIZE) {
+	if (access_bit_width == ACPI_INTEGER_BIT_SIZE) {
 		width_mask = ACPI_UINT64_MAX;
 	} else {
-		width_mask =
-		    ACPI_MASK_BITS_ABOVE(obj_desc->common_field.
-					 access_bit_width);
+		width_mask = ACPI_MASK_BITS_ABOVE(access_bit_width);
 	}
 
 	mask = width_mask &
@@ -863,12 +889,11 @@
 	/* Compute the number of datums (access width data items) */
 
 	datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
-				       obj_desc->common_field.access_bit_width);
+				       access_bit_width);
 
 	field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
 					     obj_desc->common_field.
 					     start_field_bit_offset,
-					     obj_desc->common_field.
 					     access_bit_width);
 
 	/* Get initial Datum from the input buffer */
@@ -905,12 +930,11 @@
 		 * This avoids the differences in behavior between different compilers
 		 * concerning shift values larger than the target data width.
 		 */
-		if ((obj_desc->common_field.access_bit_width -
+		if ((access_bit_width -
 		     obj_desc->common_field.start_field_bit_offset) <
 		    ACPI_INTEGER_BIT_SIZE) {
 			merged_datum =
-			    raw_datum >> (obj_desc->common_field.
-					  access_bit_width -
+			    raw_datum >> (access_bit_width -
 					  obj_desc->common_field.
 					  start_field_bit_offset);
 		} else {
@@ -929,6 +953,7 @@
 		ACPI_MEMCPY(&raw_datum, ((char *)buffer) + buffer_offset,
 			    ACPI_MIN(obj_desc->common_field.access_byte_width,
 				     buffer_length - buffer_offset));
+
 		merged_datum |=
 		    raw_datum << obj_desc->common_field.start_field_bit_offset;
 	}
@@ -937,7 +962,7 @@
 
 	buffer_tail_bits = (obj_desc->common_field.bit_length +
 			    obj_desc->common_field.start_field_bit_offset) %
-	    obj_desc->common_field.access_bit_width;
+	    access_bit_width;
 	if (buffer_tail_bits) {
 		mask &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits);
 	}