Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 286736
b: refs/heads/master
c: 54d5dcc
h: refs/heads/master
v: v3
  • Loading branch information
Thomas Renninger authored and Len Brown committed Jan 20, 2012
1 parent bdd3c73 commit 4127e50
Show file tree
Hide file tree
Showing 9 changed files with 569 additions and 244 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: 459413db33d6c99fc13d60f88899fb72d2530ed3
refs/heads/master: 54d5dcc45af7adbb907072d042bbece4c2b4de6e
1 change: 1 addition & 0 deletions trunk/drivers/acpi/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ obj-y += acpi.o \

# All the builtin files are in the "acpi." module_param namespace.
acpi-y += osl.o utils.o reboot.o
acpi-y += atomicio.o
acpi-y += nvs.o

# sleep related files
Expand Down
35 changes: 31 additions & 4 deletions trunk/drivers/acpi/apei/apei-base.c
Original file line number Diff line number Diff line change
Expand Up @@ -596,19 +596,33 @@ 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_memory64((acpi_physical_address)
address, val, reg->bit_width);
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);
Expand All @@ -628,18 +642,31 @@ 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_memory64((acpi_physical_address)
address, val, reg->bit_width);
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);
Expand Down
95 changes: 48 additions & 47 deletions trunk/drivers/acpi/apei/einj.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,21 @@ static DEFINE_MUTEX(einj_mutex);

static void *einj_param;

#ifndef readq
static inline __u64 readq(volatile void __iomem *addr)
{
return ((__u64)readl(addr+4) << 32) + readl(addr);
}
#endif

#ifndef writeq
static inline void writeq(__u64 val, volatile void __iomem *addr)
{
writel(val, addr);
writel(val >> 32, addr+4);
}
#endif

static void einj_exec_ctx_init(struct apei_exec_context *ctx)
{
apei_exec_ctx_init(ctx, einj_ins_type, ARRAY_SIZE(einj_ins_type),
Expand Down Expand Up @@ -189,21 +204,22 @@ static int einj_timedout(u64 *t)
static void check_vendor_extension(u64 paddr,
struct set_error_type_with_address *v5param)
{
int offset = v5param->vendor_extension;
int offset = readl(&v5param->vendor_extension);
struct vendor_error_type_extension *v;
u32 sbdf;

if (!offset)
return;
v = acpi_os_map_memory(paddr + offset, sizeof(*v));
v = ioremap(paddr + offset, sizeof(*v));
if (!v)
return;
sbdf = v->pcie_sbdf;
sbdf = readl(&v->pcie_sbdf);
sprintf(vendor_dev, "%x:%x:%x.%x vendor_id=%x device_id=%x rev_id=%x\n",
sbdf >> 24, (sbdf >> 16) & 0xff,
(sbdf >> 11) & 0x1f, (sbdf >> 8) & 0x7,
v->vendor_id, v->device_id, v->rev_id);
acpi_os_unmap_memory(v, sizeof(*v));
readw(&v->vendor_id), readw(&v->device_id),
readb(&v->rev_id));
iounmap(v);
}

static void *einj_get_parameter_address(void)
Expand Down Expand Up @@ -231,7 +247,7 @@ static void *einj_get_parameter_address(void)
if (paddrv5) {
struct set_error_type_with_address *v5param;

v5param = acpi_os_map_memory(paddrv5, sizeof(*v5param));
v5param = ioremap(paddrv5, sizeof(*v5param));
if (v5param) {
acpi5 = 1;
check_vendor_extension(paddrv5, v5param);
Expand All @@ -241,17 +257,17 @@ static void *einj_get_parameter_address(void)
if (paddrv4) {
struct einj_parameter *v4param;

v4param = acpi_os_map_memory(paddrv4, sizeof(*v4param));
v4param = ioremap(paddrv4, sizeof(*v4param));
if (!v4param)
return NULL;
if (v4param->reserved1 || v4param->reserved2) {
acpi_os_unmap_memory(v4param, sizeof(*v4param));
return NULL;
return 0;
if (readq(&v4param->reserved1) || readq(&v4param->reserved2)) {
iounmap(v4param);
return 0;
}
return v4param;
}

return NULL;
return 0;
}

/* do sanity check to trigger table */
Expand All @@ -260,7 +276,7 @@ static int einj_check_trigger_header(struct acpi_einj_trigger *trigger_tab)
if (trigger_tab->header_size != sizeof(struct acpi_einj_trigger))
return -EINVAL;
if (trigger_tab->table_size > PAGE_SIZE ||
trigger_tab->table_size < trigger_tab->header_size)
trigger_tab->table_size <= trigger_tab->header_size)
return -EINVAL;
if (trigger_tab->entry_count !=
(trigger_tab->table_size - trigger_tab->header_size) /
Expand Down Expand Up @@ -324,11 +340,6 @@ static int __einj_error_trigger(u64 trigger_paddr, u32 type,
"The trigger error action table is invalid\n");
goto out_rel_header;
}

/* No action structures in the TRIGGER_ERROR table, nothing to do */
if (!trigger_tab->entry_count)
goto out_rel_header;

rc = -EIO;
table_size = trigger_tab->table_size;
r = request_mem_region(trigger_paddr + sizeof(*trigger_tab),
Expand Down Expand Up @@ -424,41 +435,41 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2)
if (acpi5) {
struct set_error_type_with_address *v5param = einj_param;

v5param->type = type;
writel(type, &v5param->type);
if (type & 0x80000000) {
switch (vendor_flags) {
case SETWA_FLAGS_APICID:
v5param->apicid = param1;
writel(param1, &v5param->apicid);
break;
case SETWA_FLAGS_MEM:
v5param->memory_address = param1;
v5param->memory_address_range = param2;
writeq(param1, &v5param->memory_address);
writeq(param2, &v5param->memory_address_range);
break;
case SETWA_FLAGS_PCIE_SBDF:
v5param->pcie_sbdf = param1;
writel(param1, &v5param->pcie_sbdf);
break;
}
v5param->flags = vendor_flags;
writel(vendor_flags, &v5param->flags);
} else {
switch (type) {
case ACPI_EINJ_PROCESSOR_CORRECTABLE:
case ACPI_EINJ_PROCESSOR_UNCORRECTABLE:
case ACPI_EINJ_PROCESSOR_FATAL:
v5param->apicid = param1;
v5param->flags = SETWA_FLAGS_APICID;
writel(param1, &v5param->apicid);
writel(SETWA_FLAGS_APICID, &v5param->flags);
break;
case ACPI_EINJ_MEMORY_CORRECTABLE:
case ACPI_EINJ_MEMORY_UNCORRECTABLE:
case ACPI_EINJ_MEMORY_FATAL:
v5param->memory_address = param1;
v5param->memory_address_range = param2;
v5param->flags = SETWA_FLAGS_MEM;
writeq(param1, &v5param->memory_address);
writeq(param2, &v5param->memory_address_range);
writel(SETWA_FLAGS_MEM, &v5param->flags);
break;
case ACPI_EINJ_PCIX_CORRECTABLE:
case ACPI_EINJ_PCIX_UNCORRECTABLE:
case ACPI_EINJ_PCIX_FATAL:
v5param->pcie_sbdf = param1;
v5param->flags = SETWA_FLAGS_PCIE_SBDF;
writel(param1, &v5param->pcie_sbdf);
writel(SETWA_FLAGS_PCIE_SBDF, &v5param->flags);
break;
}
}
Expand All @@ -468,8 +479,8 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2)
return rc;
if (einj_param) {
struct einj_parameter *v4param = einj_param;
v4param->param1 = param1;
v4param->param2 = param2;
writeq(param1, &v4param->param1);
writeq(param2, &v4param->param2);
}
}
rc = apei_exec_run(&ctx, ACPI_EINJ_EXECUTE_OPERATION);
Expand Down Expand Up @@ -720,13 +731,8 @@ static int __init einj_init(void)
return 0;

err_unmap:
if (einj_param) {
acpi_size size = (acpi5) ?
sizeof(struct set_error_type_with_address) :
sizeof(struct einj_parameter);

acpi_os_unmap_memory(einj_param, size);
}
if (einj_param)
iounmap(einj_param);
apei_exec_post_unmap_gars(&ctx);
err_release:
apei_resources_release(&einj_resources);
Expand All @@ -742,13 +748,8 @@ static void __exit einj_exit(void)
{
struct apei_exec_context ctx;

if (einj_param) {
acpi_size size = (acpi5) ?
sizeof(struct set_error_type_with_address) :
sizeof(struct einj_parameter);

acpi_os_unmap_memory(einj_param, size);
}
if (einj_param)
iounmap(einj_param);
einj_exec_ctx_init(&ctx);
apei_exec_post_unmap_gars(&ctx);
apei_resources_release(&einj_resources);
Expand Down
Loading

0 comments on commit 4127e50

Please sign in to comment.