Commit cb797175 authored by Len Brown's avatar Len Brown

Merge branch 'atomicio-remove' into release

parents 037d76f4 700130b4
...@@ -34,13 +34,13 @@ ...@@ -34,13 +34,13 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/acpi_io.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/kref.h> #include <linux/kref.h>
#include <linux/rculist.h> #include <linux/rculist.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <acpi/atomicio.h>
#include "apei-internal.h" #include "apei-internal.h"
...@@ -70,7 +70,7 @@ int __apei_exec_read_register(struct acpi_whea_header *entry, u64 *val) ...@@ -70,7 +70,7 @@ int __apei_exec_read_register(struct acpi_whea_header *entry, u64 *val)
{ {
int rc; int rc;
rc = acpi_atomic_read(val, &entry->register_region); rc = apei_read(val, &entry->register_region);
if (rc) if (rc)
return rc; return rc;
*val >>= entry->register_region.bit_offset; *val >>= entry->register_region.bit_offset;
...@@ -116,13 +116,13 @@ int __apei_exec_write_register(struct acpi_whea_header *entry, u64 val) ...@@ -116,13 +116,13 @@ int __apei_exec_write_register(struct acpi_whea_header *entry, u64 val)
val <<= entry->register_region.bit_offset; val <<= entry->register_region.bit_offset;
if (entry->flags & APEI_EXEC_PRESERVE_REGISTER) { if (entry->flags & APEI_EXEC_PRESERVE_REGISTER) {
u64 valr = 0; u64 valr = 0;
rc = acpi_atomic_read(&valr, &entry->register_region); rc = apei_read(&valr, &entry->register_region);
if (rc) if (rc)
return rc; return rc;
valr &= ~(entry->mask << entry->register_region.bit_offset); valr &= ~(entry->mask << entry->register_region.bit_offset);
val |= valr; val |= valr;
} }
rc = acpi_atomic_write(val, &entry->register_region); rc = apei_write(val, &entry->register_region);
return rc; return rc;
} }
...@@ -243,7 +243,7 @@ static int pre_map_gar_callback(struct apei_exec_context *ctx, ...@@ -243,7 +243,7 @@ static int pre_map_gar_callback(struct apei_exec_context *ctx,
u8 ins = entry->instruction; u8 ins = entry->instruction;
if (ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER) 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; return 0;
} }
...@@ -276,7 +276,7 @@ static int post_unmap_gar_callback(struct apei_exec_context *ctx, ...@@ -276,7 +276,7 @@ static int post_unmap_gar_callback(struct apei_exec_context *ctx,
u8 ins = entry->instruction; u8 ins = entry->instruction;
if (ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER) 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; return 0;
} }
...@@ -591,6 +591,96 @@ static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr) ...@@ -591,6 +591,96 @@ static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr)
return 0; 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, static int collect_res_callback(struct apei_exec_context *ctx,
struct acpi_whea_header *entry, struct acpi_whea_header *entry,
void *data) void *data)
......
...@@ -68,6 +68,9 @@ static inline int apei_exec_run_optional(struct apei_exec_context *ctx, u8 actio ...@@ -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 */ /* IP has been set in instruction function */
#define APEI_EXEC_SET_IP 1 #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_read_register(struct acpi_whea_header *entry, u64 *val);
int __apei_exec_write_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, int apei_exec_read_register(struct apei_exec_context *ctx,
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/acpi_io.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/timer.h> #include <linux/timer.h>
...@@ -48,7 +49,6 @@ ...@@ -48,7 +49,6 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/aer.h> #include <linux/aer.h>
#include <acpi/apei.h> #include <acpi/apei.h>
#include <acpi/atomicio.h>
#include <acpi/hed.h> #include <acpi/hed.h>
#include <asm/mce.h> #include <asm/mce.h>
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
...@@ -301,7 +301,7 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic) ...@@ -301,7 +301,7 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic)
if (!ghes) if (!ghes)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
ghes->generic = generic; ghes->generic = generic;
rc = acpi_pre_map_gar(&generic->error_status_address); rc = acpi_os_map_generic_address(&generic->error_status_address);
if (rc) if (rc)
goto err_free; goto err_free;
error_block_length = generic->error_block_length; error_block_length = generic->error_block_length;
...@@ -321,7 +321,7 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic) ...@@ -321,7 +321,7 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic)
return ghes; return ghes;
err_unmap: err_unmap:
acpi_post_unmap_gar(&generic->error_status_address); acpi_os_unmap_generic_address(&generic->error_status_address);
err_free: err_free:
kfree(ghes); kfree(ghes);
return ERR_PTR(rc); return ERR_PTR(rc);
...@@ -330,7 +330,7 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic) ...@@ -330,7 +330,7 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic)
static void ghes_fini(struct ghes *ghes) static void ghes_fini(struct ghes *ghes)
{ {
kfree(ghes->estatus); kfree(ghes->estatus);
acpi_post_unmap_gar(&ghes->generic->error_status_address); acpi_os_unmap_generic_address(&ghes->generic->error_status_address);
} }
enum { enum {
...@@ -401,7 +401,7 @@ static int ghes_read_estatus(struct ghes *ghes, int silent) ...@@ -401,7 +401,7 @@ static int ghes_read_estatus(struct ghes *ghes, int silent)
u32 len; u32 len;
int rc; int rc;
rc = acpi_atomic_read(&buf_paddr, &g->error_status_address); rc = apei_read(&buf_paddr, &g->error_status_address);
if (rc) { if (rc) {
if (!silent && printk_ratelimit()) if (!silent && printk_ratelimit())
pr_warning(FW_WARN GHES_PFX pr_warning(FW_WARN GHES_PFX
......
...@@ -153,17 +153,21 @@ static u32 acpi_osi_handler(acpi_string interface, u32 supported) ...@@ -153,17 +153,21 @@ static u32 acpi_osi_handler(acpi_string interface, u32 supported)
return 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) 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; return;
/* Resources are never freed */ /* Resources are never freed */
if (addr->space_id == ACPI_ADR_SPACE_SYSTEM_IO) if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO)
request_region(addr->address, length, desc); request_region(addr, length, desc);
else if (addr->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
request_mem_region(addr->address, length, desc); request_mem_region(addr, length, desc);
} }
static int __init acpi_reserve_resources(void) static int __init acpi_reserve_resources(void)
...@@ -414,35 +418,42 @@ void __init early_acpi_os_unmap_memory(void __iomem *virt, acpi_size size) ...@@ -414,35 +418,42 @@ void __init early_acpi_os_unmap_memory(void __iomem *virt, acpi_size size)
__acpi_unmap_table(virt, 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; void __iomem *virt;
if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) if (gas->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
return 0; 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; 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) if (!virt)
return -EIO; return -EIO;
return 0; 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; struct acpi_ioremap *map;
if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) if (gas->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
return; return;
if (!addr->address || !addr->bit_width) /* Handle possible alignment issues */
memcpy(&addr, &gas->address, sizeof(addr));
if (!addr || !gas->bit_width)
return; return;
mutex_lock(&acpi_ioremap_lock); 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) { if (!map) {
mutex_unlock(&acpi_ioremap_lock); mutex_unlock(&acpi_ioremap_lock);
return; return;
...@@ -452,6 +463,7 @@ static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr) ...@@ -452,6 +463,7 @@ static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr)
acpi_os_map_cleanup(map); acpi_os_map_cleanup(map);
} }
EXPORT_SYMBOL(acpi_os_unmap_generic_address);
#ifdef ACPI_FUTURE_USAGE #ifdef ACPI_FUTURE_USAGE
acpi_status acpi_status
......
...@@ -12,4 +12,7 @@ static inline void __iomem *acpi_os_ioremap(acpi_physical_address phys, ...@@ -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); 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 #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment