diff options
author | Myron Stowe <mstowe@redhat.com> | 2012-01-20 21:13:24 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2012-01-21 01:08:17 -0500 |
commit | e615bf5b5519862ab66172f4dec7455d6543a578 (patch) | |
tree | c6d37861dc376b55bc5c4ece88f57faf9d51e99a /drivers/acpi/apei | |
parent | dcd6c92267155e70a94b3927bce681ce74b80d1f (diff) |
ACPI, APEI: Add 64-bit read/write support for APEI on i386
Base ACPI (CA) currently does not support atomic 64-bit reads and writes
(acpi_read() and acpi_write() split 64-bit loads/stores into two
32-bit transfers) yet APEI expects 64-bit transfer capability, even
when running on 32-bit systems.
This patch implements 64-bit read and write routines for APEI usage.
This patch re-factors similar functionality introduced in commit
04c25997c97, bringing it into the ACPI subsystem in preparation for
removing ./drivers/acpi/atomicio.[ch]. In the implementation I have
replicated acpi_os_read_memory() and acpi_os_write_memory(), creating
64-bit versions for APEI to utilize, as opposed to something more
elegant. My thinking is that we should attempt to see if we can get
ACPI's CA/OSL changed so that the existing acpi_read() and acpi_write()
interfaces are natively 64-bit capable and then subsequently remove the
replication.
Signed-off-by: Myron Stowe <myron.stowe@redhat.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/apei')
-rw-r--r-- | drivers/acpi/apei/apei-base.c | 35 |
1 files changed, 4 insertions, 31 deletions
diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c index e45350cb6ac8..e5d53b7ddc7e 100644 --- a/drivers/acpi/apei/apei-base.c +++ b/drivers/acpi/apei/apei-base.c | |||
@@ -596,33 +596,19 @@ int apei_read(u64 *val, struct acpi_generic_address *reg) | |||
596 | { | 596 | { |
597 | int rc; | 597 | int rc; |
598 | u64 address; | 598 | u64 address; |
599 | u32 tmp, width = reg->bit_width; | ||
600 | acpi_status status; | 599 | acpi_status status; |
601 | 600 | ||
602 | rc = apei_check_gar(reg, &address); | 601 | rc = apei_check_gar(reg, &address); |
603 | if (rc) | 602 | if (rc) |
604 | return rc; | 603 | return rc; |
605 | 604 | ||
606 | if (width == 64) | ||
607 | width = 32; /* Break into two 32-bit transfers */ | ||
608 | |||
609 | *val = 0; | 605 | *val = 0; |
610 | switch(reg->space_id) { | 606 | switch(reg->space_id) { |
611 | case ACPI_ADR_SPACE_SYSTEM_MEMORY: | 607 | case ACPI_ADR_SPACE_SYSTEM_MEMORY: |
612 | status = acpi_os_read_memory((acpi_physical_address) | 608 | status = acpi_os_read_memory64((acpi_physical_address) |
613 | address, &tmp, width); | 609 | address, val, reg->bit_width); |
614 | if (ACPI_FAILURE(status)) | 610 | if (ACPI_FAILURE(status)) |
615 | return -EIO; | 611 | return -EIO; |
616 | *val = tmp; | ||
617 | |||
618 | if (reg->bit_width == 64) { | ||
619 | /* Read the top 32 bits */ | ||
620 | status = acpi_os_read_memory((acpi_physical_address) | ||
621 | (address + 4), &tmp, 32); | ||
622 | if (ACPI_FAILURE(status)) | ||
623 | return -EIO; | ||
624 | *val |= ((u64)tmp << 32); | ||
625 | } | ||
626 | break; | 612 | break; |
627 | case ACPI_ADR_SPACE_SYSTEM_IO: | 613 | case ACPI_ADR_SPACE_SYSTEM_IO: |
628 | status = acpi_os_read_port(address, (u32 *)val, reg->bit_width); | 614 | status = acpi_os_read_port(address, (u32 *)val, reg->bit_width); |
@@ -642,31 +628,18 @@ int apei_write(u64 val, struct acpi_generic_address *reg) | |||
642 | { | 628 | { |
643 | int rc; | 629 | int rc; |
644 | u64 address; | 630 | u64 address; |
645 | u32 width = reg->bit_width; | ||
646 | acpi_status status; | 631 | acpi_status status; |
647 | 632 | ||
648 | rc = apei_check_gar(reg, &address); | 633 | rc = apei_check_gar(reg, &address); |
649 | if (rc) | 634 | if (rc) |
650 | return rc; | 635 | return rc; |
651 | 636 | ||
652 | if (width == 64) | ||
653 | width = 32; /* Break into two 32-bit transfers */ | ||
654 | |||
655 | switch (reg->space_id) { | 637 | switch (reg->space_id) { |
656 | case ACPI_ADR_SPACE_SYSTEM_MEMORY: | 638 | case ACPI_ADR_SPACE_SYSTEM_MEMORY: |
657 | status = acpi_os_write_memory((acpi_physical_address) | 639 | status = acpi_os_write_memory64((acpi_physical_address) |
658 | address, ACPI_LODWORD(val), | 640 | address, val, reg->bit_width); |
659 | width); | ||
660 | if (ACPI_FAILURE(status)) | 641 | if (ACPI_FAILURE(status)) |
661 | return -EIO; | 642 | return -EIO; |
662 | |||
663 | if (reg->bit_width == 64) { | ||
664 | status = acpi_os_write_memory((acpi_physical_address) | ||
665 | (address + 4), | ||
666 | ACPI_HIDWORD(val), 32); | ||
667 | if (ACPI_FAILURE(status)) | ||
668 | return -EIO; | ||
669 | } | ||
670 | break; | 643 | break; |
671 | case ACPI_ADR_SPACE_SYSTEM_IO: | 644 | case ACPI_ADR_SPACE_SYSTEM_IO: |
672 | status = acpi_os_write_port(address, val, reg->bit_width); | 645 | status = acpi_os_write_port(address, val, reg->bit_width); |