]> Pileus Git - ~andy/linux/commitdiff
Merge branch 'atomicio-remove' into release
authorLen Brown <len.brown@intel.com>
Wed, 18 Jan 2012 05:46:30 +0000 (00:46 -0500)
committerLen Brown <len.brown@intel.com>
Wed, 18 Jan 2012 05:46:30 +0000 (00:46 -0500)
drivers/acpi/apei/apei-base.c
drivers/acpi/apei/apei-internal.h
drivers/acpi/apei/ghes.c
drivers/acpi/osl.c
include/linux/acpi_io.h

index 4abb6c74a9388836d82b6b8983040e2b28cf1428..e45350cb6ac8356f9bbc161344a5875a976f430b 100644 (file)
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/acpi.h>
+#include <linux/acpi_io.h>
 #include <linux/slab.h>
 #include <linux/io.h>
 #include <linux/kref.h>
 #include <linux/rculist.h>
 #include <linux/interrupt.h>
 #include <linux/debugfs.h>
-#include <acpi/atomicio.h>
 
 #include "apei-internal.h"
 
@@ -70,7 +70,7 @@ int __apei_exec_read_register(struct acpi_whea_header *entry, u64 *val)
 {
        int rc;
 
-       rc = acpi_atomic_read(val, &entry->register_region);
+       rc = apei_read(val, &entry->register_region);
        if (rc)
                return rc;
        *val >>= entry->register_region.bit_offset;
@@ -116,13 +116,13 @@ int __apei_exec_write_register(struct acpi_whea_header *entry, u64 val)
        val <<= entry->register_region.bit_offset;
        if (entry->flags & APEI_EXEC_PRESERVE_REGISTER) {
                u64 valr = 0;
-               rc = acpi_atomic_read(&valr, &entry->register_region);
+               rc = apei_read(&valr, &entry->register_region);
                if (rc)
                        return rc;
                valr &= ~(entry->mask << entry->register_region.bit_offset);
                val |= valr;
        }
-       rc = acpi_atomic_write(val, &entry->register_region);
+       rc = apei_write(val, &entry->register_region);
 
        return rc;
 }
@@ -243,7 +243,7 @@ static int pre_map_gar_callback(struct apei_exec_context *ctx,
        u8 ins = entry->instruction;
 
        if (ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER)
-               return acpi_pre_map_gar(&entry->register_region);
+               return acpi_os_map_generic_address(&entry->register_region);
 
        return 0;
 }
@@ -276,7 +276,7 @@ static int post_unmap_gar_callback(struct apei_exec_context *ctx,
        u8 ins = entry->instruction;
 
        if (ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER)
-               acpi_post_unmap_gar(&entry->register_region);
+               acpi_os_unmap_generic_address(&entry->register_region);
 
        return 0;
 }
@@ -591,6 +591,96 @@ static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr)
        return 0;
 }
 
+/* read GAR in interrupt (including NMI) or process context */
+int apei_read(u64 *val, struct acpi_generic_address *reg)
+{
+       int rc;
+       u64 address;
+       u32 tmp, width = reg->bit_width;
+       acpi_status status;
+
+       rc = apei_check_gar(reg, &address);
+       if (rc)
+               return rc;
+
+       if (width == 64)
+               width = 32;     /* Break into two 32-bit transfers */
+
+       *val = 0;
+       switch(reg->space_id) {
+       case ACPI_ADR_SPACE_SYSTEM_MEMORY:
+               status = acpi_os_read_memory((acpi_physical_address)
+                                            address, &tmp, width);
+               if (ACPI_FAILURE(status))
+                       return -EIO;
+               *val = tmp;
+
+               if (reg->bit_width == 64) {
+                       /* Read the top 32 bits */
+                       status = acpi_os_read_memory((acpi_physical_address)
+                                                    (address + 4), &tmp, 32);
+                       if (ACPI_FAILURE(status))
+                               return -EIO;
+                       *val |= ((u64)tmp << 32);
+               }
+               break;
+       case ACPI_ADR_SPACE_SYSTEM_IO:
+               status = acpi_os_read_port(address, (u32 *)val, reg->bit_width);
+               if (ACPI_FAILURE(status))
+                       return -EIO;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(apei_read);
+
+/* write GAR in interrupt (including NMI) or process context */
+int apei_write(u64 val, struct acpi_generic_address *reg)
+{
+       int rc;
+       u64 address;
+       u32 width = reg->bit_width;
+       acpi_status status;
+
+       rc = apei_check_gar(reg, &address);
+       if (rc)
+               return rc;
+
+       if (width == 64)
+               width = 32;     /* Break into two 32-bit transfers */
+
+       switch (reg->space_id) {
+       case ACPI_ADR_SPACE_SYSTEM_MEMORY:
+               status = acpi_os_write_memory((acpi_physical_address)
+                                             address, ACPI_LODWORD(val),
+                                             width);
+               if (ACPI_FAILURE(status))
+                       return -EIO;
+
+               if (reg->bit_width == 64) {
+                       status = acpi_os_write_memory((acpi_physical_address)
+                                                     (address + 4),
+                                                     ACPI_HIDWORD(val), 32);
+                       if (ACPI_FAILURE(status))
+                               return -EIO;
+               }
+               break;
+       case ACPI_ADR_SPACE_SYSTEM_IO:
+               status = acpi_os_write_port(address, val, reg->bit_width);
+               if (ACPI_FAILURE(status))
+                       return -EIO;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(apei_write);
+
 static int collect_res_callback(struct apei_exec_context *ctx,
                                struct acpi_whea_header *entry,
                                void *data)
index d778edd34fbaec85ba0e24f0710eefaf44c543c2..cca240a33038fe148ca5e9324214ba988c62c6c2 100644 (file)
@@ -68,6 +68,9 @@ static inline int apei_exec_run_optional(struct apei_exec_context *ctx, u8 actio
 /* IP has been set in instruction function */
 #define APEI_EXEC_SET_IP       1
 
+int apei_read(u64 *val, struct acpi_generic_address *reg);
+int apei_write(u64 val, struct acpi_generic_address *reg);
+
 int __apei_exec_read_register(struct acpi_whea_header *entry, u64 *val);
 int __apei_exec_write_register(struct acpi_whea_header *entry, u64 val);
 int apei_exec_read_register(struct apei_exec_context *ctx,
index aaf36090de1e242ce96d5df4e990d7c842f43c05..b3207e16670e5a231ae6d0c72ee226f2415a8efc 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/acpi.h>
+#include <linux/acpi_io.h>
 #include <linux/io.h>
 #include <linux/interrupt.h>
 #include <linux/timer.h>
@@ -48,7 +49,6 @@
 #include <linux/pci.h>
 #include <linux/aer.h>
 #include <acpi/apei.h>
-#include <acpi/atomicio.h>
 #include <acpi/hed.h>
 #include <asm/mce.h>
 #include <asm/tlbflush.h>
@@ -301,7 +301,7 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic)
        if (!ghes)
                return ERR_PTR(-ENOMEM);
        ghes->generic = generic;
-       rc = acpi_pre_map_gar(&generic->error_status_address);
+       rc = acpi_os_map_generic_address(&generic->error_status_address);
        if (rc)
                goto err_free;
        error_block_length = generic->error_block_length;
@@ -321,7 +321,7 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic)
        return ghes;
 
 err_unmap:
-       acpi_post_unmap_gar(&generic->error_status_address);
+       acpi_os_unmap_generic_address(&generic->error_status_address);
 err_free:
        kfree(ghes);
        return ERR_PTR(rc);
@@ -330,7 +330,7 @@ err_free:
 static void ghes_fini(struct ghes *ghes)
 {
        kfree(ghes->estatus);
-       acpi_post_unmap_gar(&ghes->generic->error_status_address);
+       acpi_os_unmap_generic_address(&ghes->generic->error_status_address);
 }
 
 enum {
@@ -401,7 +401,7 @@ static int ghes_read_estatus(struct ghes *ghes, int silent)
        u32 len;
        int rc;
 
-       rc = acpi_atomic_read(&buf_paddr, &g->error_status_address);
+       rc = apei_read(&buf_paddr, &g->error_status_address);
        if (rc) {
                if (!silent && printk_ratelimit())
                        pr_warning(FW_WARN GHES_PFX
index 3e57fbdf50a38d8420a5ba28f32b613be8884c18..fcc12d842bcc51cf0413e7316ac6dcf9e4cf0a1f 100644 (file)
@@ -153,17 +153,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)
@@ -414,35 +418,42 @@ 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)
+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;
 }
+EXPORT_SYMBOL(acpi_os_map_generic_address);
 
-static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr)
+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;
@@ -452,6 +463,7 @@ static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr)
 
        acpi_os_map_cleanup(map);
 }
+EXPORT_SYMBOL(acpi_os_unmap_generic_address);
 
 #ifdef ACPI_FUTURE_USAGE
 acpi_status
index 4afd7102459d7fbdef49be451141e16b0591f5e7..b0ffa219993ec2be82a01854718d5e1269ef05bb 100644 (file)
@@ -12,4 +12,7 @@ static inline void __iomem *acpi_os_ioremap(acpi_physical_address phys,
 
 void __iomem *acpi_os_get_iomem(acpi_physical_address phys, unsigned int size);
 
+int acpi_os_map_generic_address(struct acpi_generic_address *addr);
+void acpi_os_unmap_generic_address(struct acpi_generic_address *addr);
+
 #endif