diff options
author | Lv Zheng <lv.zheng@intel.com> | 2016-11-09 04:05:05 +0800 |
---|---|---|
committer | Lv Zheng <lv.zheng@intel.com> | 2016-11-09 04:05:05 +0800 |
commit | 1869476aed159647393a7040ead48bf1e943c1f2 (patch) | |
tree | 2768b200555d91d2a50450a39f8fb56d2bd9427f | |
parent | f7e7a208521265b14bcd9bb632f99a433d4f3f09 (diff) | |
download | acpica-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.c | 54 |
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) { |