diff options
author | Myron Stowe <mstowe@redhat.com> | 2011-11-07 16:23:27 -0700 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2012-01-17 04:33:40 -0500 |
commit | bc9ffce27962c0c5fdc6adf74790ea0fcbe4a99c (patch) | |
tree | 4708702e1d6302dd8b4c16df9f44853ed2128ee1 /drivers/acpi | |
parent | 4134b8c8811f23aa8a281db50dcee64dda414736 (diff) | |
download | linux-bc9ffce27962c0c5fdc6adf74790ea0fcbe4a99c.tar.bz2 |
ACPI: Fix possible alignment issues with GAS 'address' references
Generic Address Structures (GAS) may reside within ACPI tables which
are byte aligned. This patch copies GAS 'address' references to a local
variable, which will be naturally aligned, to be used going forward.
ACPI Generic Address Structure (GAS) reference:
ACPI Specification, Revision 4.0, Section 5.2.3.1, "Generic Address
Structure"
Signed-off-by: Myron Stowe <myron.stowe@redhat.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/osl.c | 38 |
1 files changed, 24 insertions, 14 deletions
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index f31c5c5f1b7e..2e285cdbefb1 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -166,17 +166,21 @@ static u32 acpi_osi_handler(acpi_string interface, u32 supported) return supported; } -static void __init acpi_request_region (struct acpi_generic_address *addr, +static void __init acpi_request_region (struct acpi_generic_address *gas, unsigned int length, char *desc) { - if (!addr->address || !length) + u64 addr; + + /* Handle possible alignment issues */ + memcpy(&addr, &gas->address, sizeof(addr)); + if (!addr || !length) return; /* Resources are never freed */ - if (addr->space_id == ACPI_ADR_SPACE_SYSTEM_IO) - request_region(addr->address, length, desc); - else if (addr->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) - request_mem_region(addr->address, length, desc); + if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO) + request_region(addr, length, desc); + else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) + request_mem_region(addr, length, desc); } static int __init acpi_reserve_resources(void) @@ -427,35 +431,41 @@ void __init early_acpi_os_unmap_memory(void __iomem *virt, acpi_size size) __acpi_unmap_table(virt, size); } -static int acpi_os_map_generic_address(struct acpi_generic_address *addr) +static int acpi_os_map_generic_address(struct acpi_generic_address *gas) { + u64 addr; void __iomem *virt; - if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) + if (gas->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) return 0; - if (!addr->address || !addr->bit_width) + /* Handle possible alignment issues */ + memcpy(&addr, &gas->address, sizeof(addr)); + if (!addr || !gas->bit_width) return -EINVAL; - virt = acpi_os_map_memory(addr->address, addr->bit_width / 8); + virt = acpi_os_map_memory(addr, gas->bit_width / 8); if (!virt) return -EIO; return 0; } -static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr) +static void acpi_os_unmap_generic_address(struct acpi_generic_address *gas) { + u64 addr; struct acpi_ioremap *map; - if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) + if (gas->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) return; - if (!addr->address || !addr->bit_width) + /* Handle possible alignment issues */ + memcpy(&addr, &gas->address, sizeof(addr)); + if (!addr || !gas->bit_width) return; mutex_lock(&acpi_ioremap_lock); - map = acpi_map_lookup(addr->address, addr->bit_width / 8); + map = acpi_map_lookup(addr, gas->bit_width / 8); if (!map) { mutex_unlock(&acpi_ioremap_lock); return; |