Skip to content

Commit 7f9bef9

Browse files
Lv Zhengrafaeljw
authored andcommitted
ACPICA / Hardware: Fix old register check in acpi_hw_get_access_bit_width()
The address check in acpi_hw_get_access_bit_width() should be byte width based, not bit width based. This patch fixes this mistake. For those who want to review acpi_hw_access_bit_width(), here is the concerns and the design details of the function: It is supposed that the GAS Address field should be aligned to the byte width indicated by the GAS AccessSize field. Similarly, for the old non GAS register, it is supposed that its Address should be aligned to its Length. For the "AccessSize = 0 (meaning ANY)" case, we try to return the maximum instruction width (64 for MMIO or 32 for PIO) or the user expected access bit width (64 for acpi_read()/acpi_write() or 32 for acpi_hw_read()/ acpi_hw_write()) and it is supposed that the GAS Address field should always be aligned to the maximum expected access bit width (otherwise it can't be accessed using ANY access bit width). The problem is in acpi_tb_init_generic_address(), where the non GAS register's Length is converted into the GAS BitWidth field, its Address is converted into the GAS Address field, and the GAS AccessSize field is left 0 but most of the registers actually cannot be accessed using "ANY" accesses. As a conclusion, when AccessSize = 0 (ANY), the Address should either be aligned to the BitWidth (wrong conversion) or aligned to 32 for PIO or 64 for MMIO (real GAS). Since currently, max_bit_width is 32, then: 1. BitWidth for the wrong conversion is 8,16,32; and 2. The Address of the real GAS should always be aligned to 8,16,32. The address alignment check to exclude false matched real GAS is not necessary. Thus this patch fixes the issue by removing the address alignment check. On the other hand, we in fact could use a simpler check of "reg->bit_width < max_bit_width" to exclude the "BitWidth=64 PIO" case that may be issued from acpi_read()/acpi_write() in the future. Fixes: b314a17 (ACPICA: Hardware: Add optimized access bit width support) Reported-and-tested-by: Boris Ostrovsky <[email protected]> Acked-by: Mike Marshall <[email protected]> Suggested-by: Jan Beulich <[email protected]> Signed-off-by: Lv Zheng <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent d1ce3bb commit 7f9bef9

File tree

1 file changed

+9
-14
lines changed

1 file changed

+9
-14
lines changed

drivers/acpi/acpica/hwregs.c

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -83,27 +83,22 @@ acpi_hw_write_multiple(u32 value,
8383
static u8
8484
acpi_hw_get_access_bit_width(struct acpi_generic_address *reg, u8 max_bit_width)
8585
{
86-
u64 address;
87-
8886
if (!reg->access_width) {
87+
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
88+
max_bit_width = 32;
89+
}
90+
8991
/*
9092
* Detect old register descriptors where only the bit_width field
91-
* makes senses. The target address is copied to handle possible
92-
* alignment issues.
93+
* makes senses.
9394
*/
94-
ACPI_MOVE_64_TO_64(&address, &reg->address);
95-
if (!reg->bit_offset && reg->bit_width &&
95+
if (reg->bit_width < max_bit_width &&
96+
!reg->bit_offset && reg->bit_width &&
9697
ACPI_IS_POWER_OF_TWO(reg->bit_width) &&
97-
ACPI_IS_ALIGNED(reg->bit_width, 8) &&
98-
ACPI_IS_ALIGNED(address, reg->bit_width)) {
98+
ACPI_IS_ALIGNED(reg->bit_width, 8)) {
9999
return (reg->bit_width);
100-
} else {
101-
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
102-
return (32);
103-
} else {
104-
return (max_bit_width);
105-
}
106100
}
101+
return (max_bit_width);
107102
} else {
108103
return (1 << (reg->access_width + 2));
109104
}

0 commit comments

Comments
 (0)