From: Len Brown <lenb@kernel.org>
To: linux-acpi@vger.kernel.org, linux-pm@lists.linux-foundation.org,
linux-kernel@vger.kernel.org
Cc: Myron Stowe <mstowe@redhat.com>,
Myron Stowe <myron.stowe@redhat.com>,
Len Brown <len.brown@intel.com>
Subject: [PATCH 41/50] ACPI APEI: Convert atomicio routines
Date: Tue, 17 Jan 2012 07:21:33 -0500 [thread overview]
Message-ID: <700130b41f4ee54520ac2ef2f7f1d072789711a4.1326802230.git.len.brown@intel.com> (raw)
In-Reply-To: <1326802902-21583-1-git-send-email-lenb@kernel.org>
In-Reply-To: <553575f1ae048aa44682b46b3c51929a0b3ad337.1326802228.git.len.brown@intel.com>
From: Myron Stowe <mstowe@redhat.com>
APEI needs memory access in interrupt context. The obvious choice is
acpi_read(), but originally it couldn't be used in interrupt context
because it makes temporary mappings with ioremap(). Therefore, we added
drivers/acpi/atomicio.c, which provides:
acpi_pre_map_gar() -- ioremap in process context
acpi_atomic_read() -- memory access in interrupt context
acpi_post_unmap_gar() -- iounmap
Later we added acpi_os_map_generic_address() (2971852) and enhanced
acpi_read() so it works in interrupt context as long as the address has
been previously mapped (620242a). Now this sequence:
acpi_os_map_generic_address() -- ioremap in process context
acpi_read()/apei_read() -- now OK in interrupt context
acpi_os_unmap_generic_address()
is equivalent to what atomicio.c provides.
This patch introduces apei_read() and apei_write(), which currently are
functional equivalents of acpi_read() and acpi_write(). This is mainly
proactive, to prevent APEI breakages if acpi_read() and acpi_write()
are ever augmented to support the 'bit_offset' field of GAS, as APEI's
__apei_exec_write_register() precludes splitting up functionality
related to 'bit_offset' and APEI's 'mask' (see its
APEI_EXEC_PRESERVE_REGISTER block).
With apei_read() and apei_write() in place, usages of atomicio routines
are converted to apei_read()/apei_write() and existing calls within
osl.c and the CA, based on the re-factoring that was done in an earlier
patch series - http://marc.info/?l=linux-acpi&m=128769263327206&w=2:
acpi_pre_map_gar() --> acpi_os_map_generic_address()
acpi_post_unmap_gar() --> acpi_os_unmap_generic_address()
acpi_atomic_read() --> apei_read()
acpi_atomic_write() --> apei_write()
Note that acpi_read() and acpi_write() currently use 'bit_width'
for accessing GARs which seems incorrect. 'bit_width' is the size of
the register, while 'access_width' is the size of the access the
processor must generate on the bus. The 'access_width' may be larger,
for example, if the hardware only supports 32-bit or 64-bit reads. I
wanted to minimize any possible impacts with this patch series so I
did *not* change this behavior.
Signed-off-by: Myron Stowe <myron.stowe@redhat.com>
Signed-off-by: Len Brown <len.brown@intel.com>
---
drivers/acpi/apei/apei-base.c | 102 ++++++++++++++++++++++++++++++++++--
drivers/acpi/apei/apei-internal.h | 3 +
drivers/acpi/apei/ghes.c | 10 ++--
3 files changed, 104 insertions(+), 11 deletions(-)
diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c
index 4abb6c7..e45350c 100644
--- a/drivers/acpi/apei/apei-base.c
+++ b/drivers/acpi/apei/apei-base.c
@@ -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"
@@ -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;
@@ -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;
}
@@ -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;
}
@@ -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;
}
@@ -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)
diff --git a/drivers/acpi/apei/apei-internal.h b/drivers/acpi/apei/apei-internal.h
index d778edd..cca240a 100644
--- a/drivers/acpi/apei/apei-internal.h
+++ b/drivers/acpi/apei/apei-internal.h
@@ -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,
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index aaf3609..b3207e1 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -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>
@@ -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>
@@ -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;
@@ -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);
@@ -330,7 +330,7 @@ err_free:
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 {
@@ -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
--
1.7.9.rc1
next prev parent reply other threads:[~2012-01-17 12:23 UTC|newest]
Thread overview: 53+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-01-17 12:20 ACPI & Power Management Patches for 3.3 Len Brown
2012-01-17 12:20 ` [PATCH 01/50] tools turbostat: recognize and run properly on IVB Len Brown
2012-01-17 12:20 ` [PATCH 02/50] ACPICA: Put back the call to acpi_os_validate_address Len Brown
2012-01-17 12:20 ` [PATCH 03/50] ACPICA: Update for GCC 4 Len Brown
2012-01-17 12:20 ` [PATCH 04/50] ACPICA: Fix to allow region arguments to reference other scopes Len Brown
2012-03-01 15:27 ` Jonathan Nieder
2012-01-17 12:20 ` [PATCH 05/50] ACPICA: Add error msg for unsupported I/O requests (not 8/16/32 bit length) Len Brown
2012-01-17 12:20 ` [PATCH 06/50] ACPICA: Add error msg for Index/Bank field registers out-of-range Len Brown
2012-01-17 12:20 ` [PATCH 07/50] ACPICA: Do not abort table load on invalid space ID Len Brown
2012-01-17 12:21 ` [PATCH 08/50] ACPI 5.0: Basic support for FADT version 5 Len Brown
2012-01-17 12:21 ` [PATCH 09/50] ACPI 5.0: Implement hardware-reduced option Len Brown
2012-01-17 12:21 ` [PATCH 10/50] ACPI 5.0: Add new/changed tables to headers Len Brown
2012-01-17 12:21 ` [PATCH 11/50] ACPI 5.0: New interfaces to allow driver access to AML mutex objects Len Brown
2012-01-17 12:21 ` [PATCH 12/50] ACPI 5.0: Implement Connection() and AccessAs() changes Len Brown
2012-01-17 12:21 ` [PATCH 13/50] ACPI 5.0: Support for GeneralPurposeIo and GenericSerialBus operation region Len Brown
2012-01-17 12:21 ` [PATCH 14/50] ACPI 5.0: Support for all new resource descriptors Len Brown
2012-01-17 12:21 ` [PATCH 15/50] ACPI 5.0: New interface, acpi_get_event_resources Len Brown
2012-01-17 12:21 ` [PATCH 16/50] ACPI 5.0: New interface, acpi_buffer_to_resource Len Brown
2012-01-17 12:21 ` [PATCH 17/50] ACPI 5.0: Add new predefined names Len Brown
2012-01-17 12:21 ` [PATCH 18/50] ACPI 5.0: Allow _AEI method in walk resources Len Brown
2012-01-17 12:21 ` [PATCH 19/50] ACPICA: Clean up Makefile Len Brown
2012-01-17 12:21 ` [PATCH 20/50] ACPICA: Update to version 20111123 Len Brown
2012-01-17 12:21 ` [PATCH 21/50] ACPICA: Update for larger ACPI 5 FADT size Len Brown
2012-01-17 12:21 ` [PATCH 22/50] ACPICA: Add support for region address conflict checking Len Brown
2012-01-17 12:21 ` [PATCH 23/50] ACPICA: Update all copyrights to 2012 Len Brown
2012-01-17 12:21 ` [PATCH 24/50] ACPICA: Update to version 20120111 Len Brown
2012-01-17 12:21 ` [PATCH 25/50] ACPI, Add 64bit read/write support to atomicio on i386 Len Brown
2012-01-17 12:21 ` [PATCH 26/50] ACPI, APEI, GHES: Add PCIe AER recovery support Len Brown
2012-01-17 12:21 ` [PATCH 27/50] ACPI, APEI, Print resource errors in conventional format Len Brown
2012-01-17 12:21 ` [PATCH 28/50] ACPI, APEI, Remove table not found message Len Brown
2012-01-17 12:21 ` [PATCH 29/50] ACPI, APEI, GHES, Distinguish interleaved error report in kernel log Len Brown
2012-01-17 12:21 ` [PATCH 30/50] ACPI, APEI, Printk queued error record before panic Len Brown
2012-01-17 12:21 ` [PATCH 31/50] ACPI, Add RAM mapping support to ACPI atomic IO support Len Brown
2012-01-17 12:21 ` [PATCH 32/50] ACPI, APEI, EINJ, Fix resource conflict on some machine Len Brown
2012-01-17 12:21 ` [PATCH 33/50] ACPI, APEI, EINJ, Refine the fix of resource conflict Len Brown
2012-01-17 12:21 ` [PATCH 34/50] ACPI, Record ACPI NVS regions Len Brown
2012-01-17 12:21 ` [PATCH 35/50] ACPI, APEI, Resolve false conflict between ACPI NVS and APEI Len Brown
2012-01-17 12:21 ` [PATCH 36/50] ACPI: Store SRAT table revision Len Brown
2012-01-17 12:21 ` [PATCH 37/50] ACPI, x86: Use SRAT table rev to use 8bit or 32bit PXM fields (x86/x86-64) Len Brown
2012-01-17 12:21 ` [PATCH 38/50] ACPI, ia64: Use SRAT table rev to use 8bit or 16/32bit PXM fields (ia64) Len Brown
2012-01-17 12:21 ` [PATCH 39/50] ACPI: Fix possible alignment issues with GAS 'address' references Len Brown
2012-01-17 12:21 ` [PATCH 40/50] ACPI: Export interfaces for ioremapping/iounmapping ACPI registers Len Brown
2012-01-17 12:21 ` Len Brown [this message]
2012-01-17 12:21 ` [PATCH 42/50] acpi/apei/einj: Add extensions to EINJ from rev 5.0 of acpi spec Len Brown
2012-01-17 12:21 ` [PATCH 43/50] intel_idle: fix API misuse Len Brown
2012-01-17 12:21 ` [PATCH 44/50] intel_idle: disable auto_demotion for hotplugged CPUs Len Brown
2012-01-17 12:21 ` [PATCH 45/50] intel_idle: remove redundant local_irq_disable() call Len Brown
2012-01-17 12:21 ` [PATCH 46/50] ACPI: kernel-parameters.txt : Add intel_idle.max_cstate Len Brown
2012-01-17 12:21 ` [PATCH 47/50] ACPI: processor: fix acpi_get_cpuid for UP processor Len Brown
2012-01-17 12:21 ` [PATCH 48/50] intel_idle: Fix a cast to pointer from integer of different size warning in intel_idle Len Brown
2012-01-17 12:21 ` [PATCH 49/50] intel idle: Make idle driver more robust Len Brown
2012-01-17 12:21 ` [PATCH 50/50] ACPI processor: Fix error path, also remove sysdev link Len Brown
2012-01-17 22:17 ` ACPI & Power Management Patches for 3.3 Holger Macht
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=700130b41f4ee54520ac2ef2f7f1d072789711a4.1326802230.git.len.brown@intel.com \
--to=lenb@kernel.org \
--cc=len.brown@intel.com \
--cc=linux-acpi@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@lists.linux-foundation.org \
--cc=mstowe@redhat.com \
--cc=myron.stowe@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®