Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 286489
b: refs/heads/master
c: 700130b
h: refs/heads/master
i:
  286487: 183413a
v: v3
  • Loading branch information
Myron Stowe authored and Len Brown committed Jan 17, 2012
1 parent 4b1ca86 commit 88946cf
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 12 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 6f68c91c55ea3576d366797fa8d45e31c4aa79f8
refs/heads/master: 700130b41f4ee54520ac2ef2f7f1d072789711a4
102 changes: 96 additions & 6 deletions trunk/drivers/acpi/apei/apei-base.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@
#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"

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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)
Expand Down
3 changes: 3 additions & 0 deletions trunk/drivers/acpi/apei/apei-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
10 changes: 5 additions & 5 deletions trunk/drivers/acpi/apei/ghes.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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>
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -330,7 +330,7 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic)
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 {
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 88946cf

Please sign in to comment.