Patchwork [1/1] ACPI: EC: Allow multibyte access to EC (v3)

login
register
mail settings
Submitter Andy Whitcroft
Date April 21, 2010, 9:21 a.m.
Message ID <1271841699-4782-2-git-send-email-apw@canonical.com>
Download mbox | patch
Permalink /patch/50645/
State Accepted
Delegated to: Andy Whitcroft
Headers show

Comments

Andy Whitcroft - April 21, 2010, 9:21 a.m.
Allow more than a single byte to be read or written to the EC.  This is
needed by some Dell BIOSs.  Do not allow access to exceed 64 bits as the
underlying algorith assumes it can do single aligned accesses of this size.

Based on the original version by Alexey Starikovskiy.

BugLink: http://bugs.launchpad.net/bugs/526354
Signed-off-by: Andy Whitcroft <apw@canonical.com>
---
 drivers/acpi/acpica/exprep.c |   17 +++++++++++++++++
 drivers/acpi/ec.c            |    7 ++-----
 2 files changed, 19 insertions(+), 5 deletions(-)
Stefan Bader - April 21, 2010, 4:21 p.m.
Just as a formality: I would make that a SAUCE patch as upstream has this in two
patches which also are different in the fact that the loop might exit
prematurely for them.

Andy Whitcroft wrote:
> Allow more than a single byte to be read or written to the EC.  This is
> needed by some Dell BIOSs.  Do not allow access to exceed 64 bits as the
> underlying algorith assumes it can do single aligned accesses of this size.
> 
> Based on the original version by Alexey Starikovskiy.
> 
> BugLink: http://bugs.launchpad.net/bugs/526354
> Signed-off-by: Andy Whitcroft <apw@canonical.com>
Acked-by: Stefan Bader <stefan.bader@canonical.com>
> ---
>  drivers/acpi/acpica/exprep.c |   17 +++++++++++++++++
>  drivers/acpi/ec.c            |    7 ++-----
>  2 files changed, 19 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/acpi/acpica/exprep.c b/drivers/acpi/acpica/exprep.c
> index 52fec07..9db351e 100644
> --- a/drivers/acpi/acpica/exprep.c
> +++ b/drivers/acpi/acpica/exprep.c
> @@ -468,6 +468,23 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
>  
>  		acpi_ut_add_reference(obj_desc->field.region_obj);
>  
> +		/* allow full data read from EC address space */
> +		if (obj_desc->field.region_obj->region.space_id ==
> +			ACPI_ADR_SPACE_EC) {
> +			if (obj_desc->common_field.bit_length > 8) {
> +				int access_bit_width = ACPI_ROUND_UP(
> +					obj_desc->common_field.bit_length, 8);
> +				if (access_bit_width > sizeof(acpi_integer) * 8)
> +					access_bit_width =
> +						sizeof(acpi_integer) * 8;
> +				obj_desc->common_field.access_bit_width =
> +					 access_bit_width;
> +				obj_desc->common_field.access_byte_width =
> +					ACPI_DIV_8(access_bit_width);
> +			}
> +
> +		}
> +
>  		ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
>  				  "RegionField: BitOff %X, Off %X, Gran %X, Region %p\n",
>  				  obj_desc->field.start_field_bit_offset,
> diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
> index f1670e0..b654a96 100644
> --- a/drivers/acpi/ec.c
> +++ b/drivers/acpi/ec.c
> @@ -601,10 +601,7 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
>  	if (function != ACPI_READ && function != ACPI_WRITE)
>  		return AE_BAD_PARAMETER;
>  
> -	if (bits != 8 && acpi_strict)
> -		return AE_BAD_PARAMETER;
> -
> -	if (EC_FLAGS_MSI)
> +	if (EC_FLAGS_MSI || bits > 8)
>  		acpi_ec_burst_enable(ec);
>  
>  	if (function == ACPI_READ) {
> @@ -626,7 +623,7 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
>  		}
>  	}
>  
> -	if (EC_FLAGS_MSI)
> +	if (EC_FLAGS_MSI || bits > 8)
>  		acpi_ec_burst_disable(ec);
>  
>  	switch (result) {
Andy Whitcroft - April 22, 2010, 6:22 p.m.
I suspect that in the longer term we will have to sort out the upstream
version of this and get that through stable.  Given this has been
extensivly tested I am going to apply this for now.

Applied to Lucid.

-apw

Patch

diff --git a/drivers/acpi/acpica/exprep.c b/drivers/acpi/acpica/exprep.c
index 52fec07..9db351e 100644
--- a/drivers/acpi/acpica/exprep.c
+++ b/drivers/acpi/acpica/exprep.c
@@ -468,6 +468,23 @@  acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
 
 		acpi_ut_add_reference(obj_desc->field.region_obj);
 
+		/* allow full data read from EC address space */
+		if (obj_desc->field.region_obj->region.space_id ==
+			ACPI_ADR_SPACE_EC) {
+			if (obj_desc->common_field.bit_length > 8) {
+				int access_bit_width = ACPI_ROUND_UP(
+					obj_desc->common_field.bit_length, 8);
+				if (access_bit_width > sizeof(acpi_integer) * 8)
+					access_bit_width =
+						sizeof(acpi_integer) * 8;
+				obj_desc->common_field.access_bit_width =
+					 access_bit_width;
+				obj_desc->common_field.access_byte_width =
+					ACPI_DIV_8(access_bit_width);
+			}
+
+		}
+
 		ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
 				  "RegionField: BitOff %X, Off %X, Gran %X, Region %p\n",
 				  obj_desc->field.start_field_bit_offset,
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index f1670e0..b654a96 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -601,10 +601,7 @@  acpi_ec_space_handler(u32 function, acpi_physical_address address,
 	if (function != ACPI_READ && function != ACPI_WRITE)
 		return AE_BAD_PARAMETER;
 
-	if (bits != 8 && acpi_strict)
-		return AE_BAD_PARAMETER;
-
-	if (EC_FLAGS_MSI)
+	if (EC_FLAGS_MSI || bits > 8)
 		acpi_ec_burst_enable(ec);
 
 	if (function == ACPI_READ) {
@@ -626,7 +623,7 @@  acpi_ec_space_handler(u32 function, acpi_physical_address address,
 		}
 	}
 
-	if (EC_FLAGS_MSI)
+	if (EC_FLAGS_MSI || bits > 8)
 		acpi_ec_burst_disable(ec);
 
 	switch (result) {