aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2012-01-18 00:46:30 -0500
committerLen Brown <len.brown@intel.com>2012-01-18 00:46:30 -0500
commitcb7971756b901abd61d47f6eb1011066abfb348d (patch)
treec822e575f95c6f8ee5814648f6ccc1fb3226f6fc /drivers
parent037d76f40430ba1269dc7d1fee22382cd9672997 (diff)
parent700130b41f4ee54520ac2ef2f7f1d072789711a4 (diff)
Merge branch 'atomicio-remove' into release
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/apei/apei-base.c102
-rw-r--r--drivers/acpi/apei/apei-internal.h3
-rw-r--r--drivers/acpi/apei/ghes.c10
-rw-r--r--drivers/acpi/osl.c40
4 files changed, 130 insertions, 25 deletions
diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c
index 4abb6c74a938..e45350cb6ac8 100644
--- a/drivers/acpi/apei/apei-base.c
+++ b/drivers/acpi/apei/apei-base.c
@@ -34,13 +34,13 @@
34#include <linux/module.h> 34#include <linux/module.h>
35#include <linux/init.h> 35#include <linux/init.h>
36#include <linux/acpi.h> 36#include <linux/acpi.h>
37#include <linux/acpi_io.h>
37#include <linux/slab.h> 38#include <linux/slab.h>
38#include <linux/io.h> 39#include <linux/io.h>
39#include <linux/kref.h> 40#include <linux/kref.h>
40#include <linux/rculist.h> 41#include <linux/rculist.h>
41#include <linux/interrupt.h> 42#include <linux/interrupt.h>
42#include <linux/debugfs.h> 43#include <linux/debugfs.h>
43#include <acpi/atomicio.h>
44 44
45#include "apei-internal.h" 45#include "apei-internal.h"
46 46
@@ -70,7 +70,7 @@ int __apei_exec_read_register(struct acpi_whea_header *entry, u64 *val)
70{ 70{
71 int rc; 71 int rc;
72 72
73 rc = acpi_atomic_read(val, &entry->register_region); 73 rc = apei_read(val, &entry->register_region);
74 if (rc) 74 if (rc)
75 return rc; 75 return rc;
76 *val >>= entry->register_region.bit_offset; 76 *val >>= entry->register_region.bit_offset;
@@ -116,13 +116,13 @@ int __apei_exec_write_register(struct acpi_whea_header *entry, u64 val)
116 val <<= entry->register_region.bit_offset; 116 val <<= entry->register_region.bit_offset;
117 if (entry->flags & APEI_EXEC_PRESERVE_REGISTER) { 117 if (entry->flags & APEI_EXEC_PRESERVE_REGISTER) {
118 u64 valr = 0; 118 u64 valr = 0;
119 rc = acpi_atomic_read(&valr, &entry->register_region); 119 rc = apei_read(&valr, &entry->register_region);
120 if (rc) 120 if (rc)
121 return rc; 121 return rc;
122 valr &= ~(entry->mask << entry->register_region.bit_offset); 122 valr &= ~(entry->mask << entry->register_region.bit_offset);
123 val |= valr; 123 val |= valr;
124 } 124 }
125 rc = acpi_atomic_write(val, &entry->register_region); 125 rc = apei_write(val, &entry->register_region);
126 126
127 return rc; 127 return rc;
128} 128}
@@ -243,7 +243,7 @@ static int pre_map_gar_callback(struct apei_exec_context *ctx,
243 u8 ins = entry->instruction; 243 u8 ins = entry->instruction;
244 244
245 if (ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER) 245 if (ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER)
246 return acpi_pre_map_gar(&entry->register_region); 246 return acpi_os_map_generic_address(&entry->register_region);
247 247
248 return 0; 248 return 0;
249} 249}
@@ -276,7 +276,7 @@ static int post_unmap_gar_callback(struct apei_exec_context *ctx,
276 u8 ins = entry->instruction; 276 u8 ins = entry->instruction;
277 277
278 if (ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER) 278 if (ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER)
279 acpi_post_unmap_gar(&entry->register_region); 279 acpi_os_unmap_generic_address(&entry->register_region);
280 280
281 return 0; 281 return 0;
282} 282}
@@ -591,6 +591,96 @@ static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr)
591 return 0; 591 return 0;
592} 592}
593 593
594/* read GAR in interrupt (including NMI) or process context */
595int apei_read(u64 *val, struct acpi_generic_address *reg)
596{
597 int rc;
598 u64 address;
599 u32 tmp, width = reg->bit_width;
600 acpi_status status;
601
602 rc = apei_check_gar(reg, &address);
603 if (rc)
604 return rc;
605
606 if (width == 64)
607 width = 32; /* Break into two 32-bit transfers */
608
609 *val = 0;
610 switch(reg->space_id) {
611 case ACPI_ADR_SPACE_SYSTEM_MEMORY:
612 status = acpi_os_read_memory((acpi_physical_address)
613 address, &tmp, width);
614 if (ACPI_FAILURE(status))
615 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;
627 case ACPI_ADR_SPACE_SYSTEM_IO:
628 status = acpi_os_read_port(address, (u32 *)val, reg->bit_width);
629 if (ACPI_FAILURE(status))
630 return -EIO;
631 break;
632 default:
633 return -EINVAL;
634 }
635
636 return 0;
637}
638EXPORT_SYMBOL_GPL(apei_read);
639
640/* write GAR in interrupt (including NMI) or process context */
641int apei_write(u64 val, struct acpi_generic_address *reg)
642{
643 int rc;
644 u64 address;
645 u32 width = reg->bit_width;
646 acpi_status status;
647
648 rc = apei_check_gar(reg, &address);
649 if (rc)
650 return rc;
651
652 if (width == 64)
653 width = 32; /* Break into two 32-bit transfers */
654
655 switch (reg->space_id) {
656 case ACPI_ADR_SPACE_SYSTEM_MEMORY:
657 status = acpi_os_write_memory((acpi_physical_address)
658 address, ACPI_LODWORD(val),
659 width);
660 if (ACPI_FAILURE(status))
661 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;
671 case ACPI_ADR_SPACE_SYSTEM_IO:
672 status = acpi_os_write_port(address, val, reg->bit_width);
673 if (ACPI_FAILURE(status))
674 return -EIO;
675 break;
676 default:
677 return -EINVAL;
678 }
679
680 return 0;
681}
682EXPORT_SYMBOL_GPL(apei_write);
683
594static int collect_res_callback(struct apei_exec_context *ctx, 684static int collect_res_callback(struct apei_exec_context *ctx,
595 struct acpi_whea_header *entry, 685 struct acpi_whea_header *entry,
596 void *data) 686 void *data)
diff --git a/drivers/acpi/apei/apei-internal.h b/drivers/acpi/apei/apei-internal.h
index d778edd34fba..cca240a33038 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
68/* IP has been set in instruction function */ 68/* IP has been set in instruction function */
69#define APEI_EXEC_SET_IP 1 69#define APEI_EXEC_SET_IP 1
70 70
71int apei_read(u64 *val, struct acpi_generic_address *reg);
72int apei_write(u64 val, struct acpi_generic_address *reg);
73
71int __apei_exec_read_register(struct acpi_whea_header *entry, u64 *val); 74int __apei_exec_read_register(struct acpi_whea_header *entry, u64 *val);
72int __apei_exec_write_register(struct acpi_whea_header *entry, u64 val); 75int __apei_exec_write_register(struct acpi_whea_header *entry, u64 val);
73int apei_exec_read_register(struct apei_exec_context *ctx, 76int apei_exec_read_register(struct apei_exec_context *ctx,
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index aaf36090de1e..b3207e16670e 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -33,6 +33,7 @@
33#include <linux/module.h> 33#include <linux/module.h>
34#include <linux/init.h> 34#include <linux/init.h>
35#include <linux/acpi.h> 35#include <linux/acpi.h>
36#include <linux/acpi_io.h>
36#include <linux/io.h> 37#include <linux/io.h>
37#include <linux/interrupt.h> 38#include <linux/interrupt.h>
38#include <linux/timer.h> 39#include <linux/timer.h>
@@ -48,7 +49,6 @@
48#include <linux/pci.h> 49#include <linux/pci.h>
49#include <linux/aer.h> 50#include <linux/aer.h>
50#include <acpi/apei.h> 51#include <acpi/apei.h>
51#include <acpi/atomicio.h>
52#include <acpi/hed.h> 52#include <acpi/hed.h>
53#include <asm/mce.h> 53#include <asm/mce.h>
54#include <asm/tlbflush.h> 54#include <asm/tlbflush.h>
@@ -301,7 +301,7 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic)
301 if (!ghes) 301 if (!ghes)
302 return ERR_PTR(-ENOMEM); 302 return ERR_PTR(-ENOMEM);
303 ghes->generic = generic; 303 ghes->generic = generic;
304 rc = acpi_pre_map_gar(&generic->error_status_address); 304 rc = acpi_os_map_generic_address(&generic->error_status_address);
305 if (rc) 305 if (rc)
306 goto err_free; 306 goto err_free;
307 error_block_length = generic->error_block_length; 307 error_block_length = generic->error_block_length;
@@ -321,7 +321,7 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic)
321 return ghes; 321 return ghes;
322 322
323err_unmap: 323err_unmap:
324 acpi_post_unmap_gar(&generic->error_status_address); 324 acpi_os_unmap_generic_address(&generic->error_status_address);
325err_free: 325err_free:
326 kfree(ghes); 326 kfree(ghes);
327 return ERR_PTR(rc); 327 return ERR_PTR(rc);
@@ -330,7 +330,7 @@ err_free:
330static void ghes_fini(struct ghes *ghes) 330static void ghes_fini(struct ghes *ghes)
331{ 331{
332 kfree(ghes->estatus); 332 kfree(ghes->estatus);
333 acpi_post_unmap_gar(&ghes->generic->error_status_address); 333 acpi_os_unmap_generic_address(&ghes->generic->error_status_address);
334} 334}
335 335
336enum { 336enum {
@@ -401,7 +401,7 @@ static int ghes_read_estatus(struct ghes *ghes, int silent)
401 u32 len; 401 u32 len;
402 int rc; 402 int rc;
403 403
404 rc = acpi_atomic_read(&buf_paddr, &g->error_status_address); 404 rc = apei_read(&buf_paddr, &g->error_status_address);
405 if (rc) { 405 if (rc) {
406 if (!silent && printk_ratelimit()) 406 if (!silent && printk_ratelimit())
407 pr_warning(FW_WARN GHES_PFX 407 pr_warning(FW_WARN GHES_PFX
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 3e57fbdf50a3..fcc12d842bcc 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -153,17 +153,21 @@ static u32 acpi_osi_handler(acpi_string interface, u32 supported)
153 return supported; 153 return supported;
154} 154}
155 155
156static void __init acpi_request_region (struct acpi_generic_address *addr, 156static void __init acpi_request_region (struct acpi_generic_address *gas,
157 unsigned int length, char *desc) 157 unsigned int length, char *desc)
158{ 158{
159 if (!addr->address || !length) 159 u64 addr;
160
161 /* Handle possible alignment issues */
162 memcpy(&addr, &gas->address, sizeof(addr));
163 if (!addr || !length)
160 return; 164 return;
161 165
162 /* Resources are never freed */ 166 /* Resources are never freed */
163 if (addr->space_id == ACPI_ADR_SPACE_SYSTEM_IO) 167 if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO)
164 request_region(addr->address, length, desc); 168 request_region(addr, length, desc);
165 else if (addr->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) 169 else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
166 request_mem_region(addr->address, length, desc); 170 request_mem_region(addr, length, desc);
167} 171}
168 172
169static int __init acpi_reserve_resources(void) 173static int __init acpi_reserve_resources(void)
@@ -414,35 +418,42 @@ void __init early_acpi_os_unmap_memory(void __iomem *virt, acpi_size size)
414 __acpi_unmap_table(virt, size); 418 __acpi_unmap_table(virt, size);
415} 419}
416 420
417static int acpi_os_map_generic_address(struct acpi_generic_address *addr) 421int acpi_os_map_generic_address(struct acpi_generic_address *gas)
418{ 422{
423 u64 addr;
419 void __iomem *virt; 424 void __iomem *virt;
420 425
421 if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) 426 if (gas->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
422 return 0; 427 return 0;
423 428
424 if (!addr->address || !addr->bit_width) 429 /* Handle possible alignment issues */
430 memcpy(&addr, &gas->address, sizeof(addr));
431 if (!addr || !gas->bit_width)
425 return -EINVAL; 432 return -EINVAL;
426 433
427 virt = acpi_os_map_memory(addr->address, addr->bit_width / 8); 434 virt = acpi_os_map_memory(addr, gas->bit_width / 8);
428 if (!virt) 435 if (!virt)
429 return -EIO; 436 return -EIO;
430 437
431 return 0; 438 return 0;
432} 439}
440EXPORT_SYMBOL(acpi_os_map_generic_address);
433 441
434static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr) 442void acpi_os_unmap_generic_address(struct acpi_generic_address *gas)
435{ 443{
444 u64 addr;
436 struct acpi_ioremap *map; 445 struct acpi_ioremap *map;
437 446
438 if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) 447 if (gas->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
439 return; 448 return;
440 449
441 if (!addr->address || !addr->bit_width) 450 /* Handle possible alignment issues */
451 memcpy(&addr, &gas->address, sizeof(addr));
452 if (!addr || !gas->bit_width)
442 return; 453 return;
443 454
444 mutex_lock(&acpi_ioremap_lock); 455 mutex_lock(&acpi_ioremap_lock);
445 map = acpi_map_lookup(addr->address, addr->bit_width / 8); 456 map = acpi_map_lookup(addr, gas->bit_width / 8);
446 if (!map) { 457 if (!map) {
447 mutex_unlock(&acpi_ioremap_lock); 458 mutex_unlock(&acpi_ioremap_lock);
448 return; 459 return;
@@ -452,6 +463,7 @@ static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr)
452 463
453 acpi_os_map_cleanup(map); 464 acpi_os_map_cleanup(map);
454} 465}
466EXPORT_SYMBOL(acpi_os_unmap_generic_address);
455 467
456#ifdef ACPI_FUTURE_USAGE 468#ifdef ACPI_FUTURE_USAGE
457acpi_status 469acpi_status