Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 298058
b: refs/heads/master
c: 15afae6
h: refs/heads/master
v: v3
  • Loading branch information
Gary Hade authored and Len Brown committed Mar 30, 2012
1 parent a23f07c commit db15aab
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 22 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: 6ef19ab7fa1535d35006535dba6c407dad2d845c
refs/heads/master: 15afae604651d4e17652d2ffb56f5e36f991cfef
61 changes: 40 additions & 21 deletions trunk/drivers/acpi/apei/apei-base.c
Original file line number Diff line number Diff line change
Expand Up @@ -558,33 +558,48 @@ void apei_resources_release(struct apei_resources *resources)
}
EXPORT_SYMBOL_GPL(apei_resources_release);

static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr)
static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr,
u32 *access_bit_width)
{
u32 width, space_id;
u32 bit_width, bit_offset, access_size_code, space_id;

width = reg->bit_width;
bit_width = reg->bit_width;
bit_offset = reg->bit_offset;
access_size_code = reg->access_width;
space_id = reg->space_id;
/* Handle possible alignment issues */
memcpy(paddr, &reg->address, sizeof(*paddr));
if (!*paddr) {
pr_warning(FW_BUG APEI_PFX
"Invalid physical address in GAR [0x%llx/%u/%u]\n",
*paddr, width, space_id);
"Invalid physical address in GAR [0x%llx/%u/%u/%u/%u]\n",
*paddr, bit_width, bit_offset, access_size_code,
space_id);
return -EINVAL;
}

if ((width != 8) && (width != 16) && (width != 32) && (width != 64)) {
if (access_size_code < 1 || access_size_code > 4) {
pr_warning(FW_BUG APEI_PFX
"Invalid bit width in GAR [0x%llx/%u/%u]\n",
*paddr, width, space_id);
"Invalid access size code in GAR [0x%llx/%u/%u/%u/%u]\n",
*paddr, bit_width, bit_offset, access_size_code,
space_id);
return -EINVAL;
}
*access_bit_width = 1UL << (access_size_code + 2);

if ((bit_width + bit_offset) > *access_bit_width) {
pr_warning(FW_BUG APEI_PFX
"Invalid bit width + offset in GAR [0x%llx/%u/%u/%u/%u]\n",
*paddr, bit_width, bit_offset, access_size_code,
space_id);
return -EINVAL;
}

if (space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY &&
space_id != ACPI_ADR_SPACE_SYSTEM_IO) {
pr_warning(FW_BUG APEI_PFX
"Invalid address space type in GAR [0x%llx/%u/%u]\n",
*paddr, width, space_id);
"Invalid address space type in GAR [0x%llx/%u/%u/%u/%u]\n",
*paddr, bit_width, bit_offset, access_size_code,
space_id);
return -EINVAL;
}

Expand All @@ -595,23 +610,25 @@ static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr)
int apei_read(u64 *val, struct acpi_generic_address *reg)
{
int rc;
u32 access_bit_width;
u64 address;
acpi_status status;

rc = apei_check_gar(reg, &address);
rc = apei_check_gar(reg, &address, &access_bit_width);
if (rc)
return rc;

*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_memory64((acpi_physical_address) address,
val, access_bit_width);
if (ACPI_FAILURE(status))
return -EIO;
break;
case ACPI_ADR_SPACE_SYSTEM_IO:
status = acpi_os_read_port(address, (u32 *)val, reg->bit_width);
status = acpi_os_read_port(address, (u32 *)val,
access_bit_width);
if (ACPI_FAILURE(status))
return -EIO;
break;
Expand All @@ -627,22 +644,23 @@ EXPORT_SYMBOL_GPL(apei_read);
int apei_write(u64 val, struct acpi_generic_address *reg)
{
int rc;
u32 access_bit_width;
u64 address;
acpi_status status;

rc = apei_check_gar(reg, &address);
rc = apei_check_gar(reg, &address, &access_bit_width);
if (rc)
return rc;

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_memory64((acpi_physical_address) address,
val, access_bit_width);
if (ACPI_FAILURE(status))
return -EIO;
break;
case ACPI_ADR_SPACE_SYSTEM_IO:
status = acpi_os_write_port(address, val, reg->bit_width);
status = acpi_os_write_port(address, val, access_bit_width);
if (ACPI_FAILURE(status))
return -EIO;
break;
Expand All @@ -661,23 +679,24 @@ static int collect_res_callback(struct apei_exec_context *ctx,
struct apei_resources *resources = data;
struct acpi_generic_address *reg = &entry->register_region;
u8 ins = entry->instruction;
u32 access_bit_width;
u64 paddr;
int rc;

if (!(ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER))
return 0;

rc = apei_check_gar(reg, &paddr);
rc = apei_check_gar(reg, &paddr, &access_bit_width);
if (rc)
return rc;

switch (reg->space_id) {
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
return apei_res_add(&resources->iomem, paddr,
reg->bit_width / 8);
access_bit_width / 8);
case ACPI_ADR_SPACE_SYSTEM_IO:
return apei_res_add(&resources->ioport, paddr,
reg->bit_width / 8);
access_bit_width / 8);
default:
return -EINVAL;
}
Expand Down

0 comments on commit db15aab

Please sign in to comment.