aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/apei
diff options
context:
space:
mode:
authorMyron Stowe <mstowe@redhat.com>2012-01-20 21:13:24 -0500
committerLen Brown <len.brown@intel.com>2012-01-21 01:08:17 -0500
commite615bf5b5519862ab66172f4dec7455d6543a578 (patch)
treec6d37861dc376b55bc5c4ece88f57faf9d51e99a /drivers/acpi/apei
parentdcd6c92267155e70a94b3927bce681ce74b80d1f (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.c35
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);