summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLv Zheng <lv.zheng@intel.com>2016-11-09 04:05:05 +0800
committerLv Zheng <lv.zheng@intel.com>2016-11-09 04:05:05 +0800
commit1869476aed159647393a7040ead48bf1e943c1f2 (patch)
tree2768b200555d91d2a50450a39f8fb56d2bd9427f
parentf7e7a208521265b14bcd9bb632f99a433d4f3f09 (diff)
downloadacpica-1869476aed159647393a7040ead48bf1e943c1f2.tar.gz
Hardware: Add optimized access bit width support
For Access Size = 0, it actually can use user expected access bit width. This patch implements this. Lv Zheng. The old register descriptors are translated in AcpiTbInitGenericAddress() with AccessWidth being filled with 0. This breaks code in AcpiHwGetAccessBitWidth() when the registers are 16-bit IO ports and their BitWidth fields are filled with 16. The rapid fix is meant to make code written for AcpiHwGetAccessBitWidth() regression safer before the issue is correctly fixed from AcpiTbInitGenericAddress(). Reported by John Baldwin <jhb@freebsd.org>, Jung-uk Kim <jkim@freebsd.org>, Boris Ostrovsky <boris.ostrovsky@oracle.com>, Mike Marshall <hubcap@omnibond.com>, Fixed by Lv Zheng <lv.zheng@intel.com>. Signed-off-by: Lv Zheng <lv.zheng@intel.com>
-rw-r--r--source/components/hardware/hwregs.c54
1 files changed, 52 insertions, 2 deletions
diff --git a/source/components/hardware/hwregs.c b/source/components/hardware/hwregs.c
index 89094f4cf..8a5b9bcee 100644
--- a/source/components/hardware/hwregs.c
+++ b/source/components/hardware/hwregs.c
@@ -126,6 +126,11 @@
/* Local Prototypes */
+static UINT8
+AcpiHwGetAccessBitWidth (
+ ACPI_GENERIC_ADDRESS *Reg,
+ UINT8 MaxBitWidth);
+
static ACPI_STATUS
AcpiHwReadMultiple (
UINT32 *Value,
@@ -143,6 +148,52 @@ AcpiHwWriteMultiple (
/******************************************************************************
*
+ * FUNCTION: AcpiHwGetAccessBitWidth
+ *
+ * PARAMETERS: Reg - GAS register structure
+ * MaxBitWidth - Max BitWidth supported (32 or 64)
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Obtain optimal access bit width
+ *
+ ******************************************************************************/
+
+static UINT8
+AcpiHwGetAccessBitWidth (
+ ACPI_GENERIC_ADDRESS *Reg,
+ UINT8 MaxBitWidth)
+{
+
+ if (!Reg->AccessWidth)
+ {
+ if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_IO)
+ {
+ MaxBitWidth = 32;
+ }
+
+ /*
+ * Detect old register descriptors where only the BitWidth field
+ * makes senses.
+ */
+ if (Reg->BitWidth < MaxBitWidth &&
+ !Reg->BitOffset && Reg->BitWidth &&
+ ACPI_IS_POWER_OF_TWO (Reg->BitWidth) &&
+ ACPI_IS_ALIGNED (Reg->BitWidth, 8))
+ {
+ return (Reg->BitWidth);
+ }
+ return (MaxBitWidth);
+ }
+ else
+ {
+ return (1 << (Reg->AccessWidth + 2));
+ }
+}
+
+
+/******************************************************************************
+ *
* FUNCTION: AcpiHwValidateRegister
*
* PARAMETERS: Reg - GAS register structure
@@ -206,8 +257,7 @@ AcpiHwValidateRegister (
/* Validate the BitWidth, convert AccessWidth into number of bits */
- AccessWidth = Reg->AccessWidth ? Reg->AccessWidth : 1;
- AccessWidth = 1 << (AccessWidth + 2);
+ AccessWidth = AcpiHwGetAccessBitWidth (Reg, MaxBitWidth);
BitWidth = ACPI_ROUND_UP (Reg->BitOffset + Reg->BitWidth, AccessWidth);
if (MaxBitWidth < BitWidth)
{