diff options
author | Luck, Tony <tony.luck@intel.com> | 2012-01-23 18:27:56 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2012-01-23 19:39:10 -0500 |
commit | 459413db33d6c99fc13d60f88899fb72d2530ed3 (patch) | |
tree | 3d4d5a9d0785e61dbc4dd85e9348ad48b9ed29f9 /drivers/acpi/apei/einj.c | |
parent | 29924b9f8f39e37275cff93740835d28b9e6fb36 (diff) |
Use acpi_os_map_memory() instead of ioremap() in einj driver
ioremap() has become more picky and is now spitting out console messages like:
ioremap error for 0xbddbd000-0xbddbe000, requested 0x10, got 0x0
when loading the einj driver. What we are trying to so here is map
a couple of data structures that the EINJ table points to. Perhaps
acpi_os_map_memory() is a better tool for this?
Most importantly it works, but as a side benefit it maps the structures
into kernel virtual space so we can access them with normal C memory
dereferences, so instead of using:
writel(param1, &v5param->apicid);
we can use the more natural:
v5param->apicid = param1;
Signed-off-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/apei/einj.c')
-rw-r--r-- | drivers/acpi/apei/einj.c | 82 |
1 files changed, 38 insertions, 44 deletions
diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c index c89b0e5a2293..4ca087dd5f4f 100644 --- a/drivers/acpi/apei/einj.c +++ b/drivers/acpi/apei/einj.c | |||
@@ -141,21 +141,6 @@ static DEFINE_MUTEX(einj_mutex); | |||
141 | 141 | ||
142 | static void *einj_param; | 142 | static void *einj_param; |
143 | 143 | ||
144 | #ifndef readq | ||
145 | static inline __u64 readq(volatile void __iomem *addr) | ||
146 | { | ||
147 | return ((__u64)readl(addr+4) << 32) + readl(addr); | ||
148 | } | ||
149 | #endif | ||
150 | |||
151 | #ifndef writeq | ||
152 | static inline void writeq(__u64 val, volatile void __iomem *addr) | ||
153 | { | ||
154 | writel(val, addr); | ||
155 | writel(val >> 32, addr+4); | ||
156 | } | ||
157 | #endif | ||
158 | |||
159 | static void einj_exec_ctx_init(struct apei_exec_context *ctx) | 144 | static void einj_exec_ctx_init(struct apei_exec_context *ctx) |
160 | { | 145 | { |
161 | apei_exec_ctx_init(ctx, einj_ins_type, ARRAY_SIZE(einj_ins_type), | 146 | apei_exec_ctx_init(ctx, einj_ins_type, ARRAY_SIZE(einj_ins_type), |
@@ -204,22 +189,21 @@ static int einj_timedout(u64 *t) | |||
204 | static void check_vendor_extension(u64 paddr, | 189 | static void check_vendor_extension(u64 paddr, |
205 | struct set_error_type_with_address *v5param) | 190 | struct set_error_type_with_address *v5param) |
206 | { | 191 | { |
207 | int offset = readl(&v5param->vendor_extension); | 192 | int offset = v5param->vendor_extension; |
208 | struct vendor_error_type_extension *v; | 193 | struct vendor_error_type_extension *v; |
209 | u32 sbdf; | 194 | u32 sbdf; |
210 | 195 | ||
211 | if (!offset) | 196 | if (!offset) |
212 | return; | 197 | return; |
213 | v = ioremap(paddr + offset, sizeof(*v)); | 198 | v = acpi_os_map_memory(paddr + offset, sizeof(*v)); |
214 | if (!v) | 199 | if (!v) |
215 | return; | 200 | return; |
216 | sbdf = readl(&v->pcie_sbdf); | 201 | sbdf = v->pcie_sbdf; |
217 | sprintf(vendor_dev, "%x:%x:%x.%x vendor_id=%x device_id=%x rev_id=%x\n", | 202 | sprintf(vendor_dev, "%x:%x:%x.%x vendor_id=%x device_id=%x rev_id=%x\n", |
218 | sbdf >> 24, (sbdf >> 16) & 0xff, | 203 | sbdf >> 24, (sbdf >> 16) & 0xff, |
219 | (sbdf >> 11) & 0x1f, (sbdf >> 8) & 0x7, | 204 | (sbdf >> 11) & 0x1f, (sbdf >> 8) & 0x7, |
220 | readw(&v->vendor_id), readw(&v->device_id), | 205 | v->vendor_id, v->device_id, v->rev_id); |
221 | readb(&v->rev_id)); | 206 | acpi_os_unmap_memory(v, sizeof(*v)); |
222 | iounmap(v); | ||
223 | } | 207 | } |
224 | 208 | ||
225 | static void *einj_get_parameter_address(void) | 209 | static void *einj_get_parameter_address(void) |
@@ -247,7 +231,7 @@ static void *einj_get_parameter_address(void) | |||
247 | if (paddrv5) { | 231 | if (paddrv5) { |
248 | struct set_error_type_with_address *v5param; | 232 | struct set_error_type_with_address *v5param; |
249 | 233 | ||
250 | v5param = ioremap(paddrv5, sizeof(*v5param)); | 234 | v5param = acpi_os_map_memory(paddrv5, sizeof(*v5param)); |
251 | if (v5param) { | 235 | if (v5param) { |
252 | acpi5 = 1; | 236 | acpi5 = 1; |
253 | check_vendor_extension(paddrv5, v5param); | 237 | check_vendor_extension(paddrv5, v5param); |
@@ -257,11 +241,11 @@ static void *einj_get_parameter_address(void) | |||
257 | if (paddrv4) { | 241 | if (paddrv4) { |
258 | struct einj_parameter *v4param; | 242 | struct einj_parameter *v4param; |
259 | 243 | ||
260 | v4param = ioremap(paddrv4, sizeof(*v4param)); | 244 | v4param = acpi_os_map_memory(paddrv4, sizeof(*v4param)); |
261 | if (!v4param) | 245 | if (!v4param) |
262 | return NULL; | 246 | return NULL; |
263 | if (readq(&v4param->reserved1) || readq(&v4param->reserved2)) { | 247 | if (v4param->reserved1 || v4param->reserved2) { |
264 | iounmap(v4param); | 248 | acpi_os_unmap_memory(v4param, sizeof(*v4param)); |
265 | return NULL; | 249 | return NULL; |
266 | } | 250 | } |
267 | return v4param; | 251 | return v4param; |
@@ -440,41 +424,41 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2) | |||
440 | if (acpi5) { | 424 | if (acpi5) { |
441 | struct set_error_type_with_address *v5param = einj_param; | 425 | struct set_error_type_with_address *v5param = einj_param; |
442 | 426 | ||
443 | writel(type, &v5param->type); | 427 | v5param->type = type; |
444 | if (type & 0x80000000) { | 428 | if (type & 0x80000000) { |
445 | switch (vendor_flags) { | 429 | switch (vendor_flags) { |
446 | case SETWA_FLAGS_APICID: | 430 | case SETWA_FLAGS_APICID: |
447 | writel(param1, &v5param->apicid); | 431 | v5param->apicid = param1; |
448 | break; | 432 | break; |
449 | case SETWA_FLAGS_MEM: | 433 | case SETWA_FLAGS_MEM: |
450 | writeq(param1, &v5param->memory_address); | 434 | v5param->memory_address = param1; |
451 | writeq(param2, &v5param->memory_address_range); | 435 | v5param->memory_address_range = param2; |
452 | break; | 436 | break; |
453 | case SETWA_FLAGS_PCIE_SBDF: | 437 | case SETWA_FLAGS_PCIE_SBDF: |
454 | writel(param1, &v5param->pcie_sbdf); | 438 | v5param->pcie_sbdf = param1; |
455 | break; | 439 | break; |
456 | } | 440 | } |
457 | writel(vendor_flags, &v5param->flags); | 441 | v5param->flags = vendor_flags; |
458 | } else { | 442 | } else { |
459 | switch (type) { | 443 | switch (type) { |
460 | case ACPI_EINJ_PROCESSOR_CORRECTABLE: | 444 | case ACPI_EINJ_PROCESSOR_CORRECTABLE: |
461 | case ACPI_EINJ_PROCESSOR_UNCORRECTABLE: | 445 | case ACPI_EINJ_PROCESSOR_UNCORRECTABLE: |
462 | case ACPI_EINJ_PROCESSOR_FATAL: | 446 | case ACPI_EINJ_PROCESSOR_FATAL: |
463 | writel(param1, &v5param->apicid); | 447 | v5param->apicid = param1; |
464 | writel(SETWA_FLAGS_APICID, &v5param->flags); | 448 | v5param->flags = SETWA_FLAGS_APICID; |
465 | break; | 449 | break; |
466 | case ACPI_EINJ_MEMORY_CORRECTABLE: | 450 | case ACPI_EINJ_MEMORY_CORRECTABLE: |
467 | case ACPI_EINJ_MEMORY_UNCORRECTABLE: | 451 | case ACPI_EINJ_MEMORY_UNCORRECTABLE: |
468 | case ACPI_EINJ_MEMORY_FATAL: | 452 | case ACPI_EINJ_MEMORY_FATAL: |
469 | writeq(param1, &v5param->memory_address); | 453 | v5param->memory_address = param1; |
470 | writeq(param2, &v5param->memory_address_range); | 454 | v5param->memory_address_range = param2; |
471 | writel(SETWA_FLAGS_MEM, &v5param->flags); | 455 | v5param->flags = SETWA_FLAGS_MEM; |
472 | break; | 456 | break; |
473 | case ACPI_EINJ_PCIX_CORRECTABLE: | 457 | case ACPI_EINJ_PCIX_CORRECTABLE: |
474 | case ACPI_EINJ_PCIX_UNCORRECTABLE: | 458 | case ACPI_EINJ_PCIX_UNCORRECTABLE: |
475 | case ACPI_EINJ_PCIX_FATAL: | 459 | case ACPI_EINJ_PCIX_FATAL: |
476 | writel(param1, &v5param->pcie_sbdf); | 460 | v5param->pcie_sbdf = param1; |
477 | writel(SETWA_FLAGS_PCIE_SBDF, &v5param->flags); | 461 | v5param->flags = SETWA_FLAGS_PCIE_SBDF; |
478 | break; | 462 | break; |
479 | } | 463 | } |
480 | } | 464 | } |
@@ -484,8 +468,8 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2) | |||
484 | return rc; | 468 | return rc; |
485 | if (einj_param) { | 469 | if (einj_param) { |
486 | struct einj_parameter *v4param = einj_param; | 470 | struct einj_parameter *v4param = einj_param; |
487 | writeq(param1, &v4param->param1); | 471 | v4param->param1 = param1; |
488 | writeq(param2, &v4param->param2); | 472 | v4param->param2 = param2; |
489 | } | 473 | } |
490 | } | 474 | } |
491 | rc = apei_exec_run(&ctx, ACPI_EINJ_EXECUTE_OPERATION); | 475 | rc = apei_exec_run(&ctx, ACPI_EINJ_EXECUTE_OPERATION); |
@@ -736,8 +720,13 @@ static int __init einj_init(void) | |||
736 | return 0; | 720 | return 0; |
737 | 721 | ||
738 | err_unmap: | 722 | err_unmap: |
739 | if (einj_param) | 723 | if (einj_param) { |
740 | iounmap(einj_param); | 724 | acpi_size size = (acpi5) ? |
725 | sizeof(struct set_error_type_with_address) : | ||
726 | sizeof(struct einj_parameter); | ||
727 | |||
728 | acpi_os_unmap_memory(einj_param, size); | ||
729 | } | ||
741 | apei_exec_post_unmap_gars(&ctx); | 730 | apei_exec_post_unmap_gars(&ctx); |
742 | err_release: | 731 | err_release: |
743 | apei_resources_release(&einj_resources); | 732 | apei_resources_release(&einj_resources); |
@@ -753,8 +742,13 @@ static void __exit einj_exit(void) | |||
753 | { | 742 | { |
754 | struct apei_exec_context ctx; | 743 | struct apei_exec_context ctx; |
755 | 744 | ||
756 | if (einj_param) | 745 | if (einj_param) { |
757 | iounmap(einj_param); | 746 | acpi_size size = (acpi5) ? |
747 | sizeof(struct set_error_type_with_address) : | ||
748 | sizeof(struct einj_parameter); | ||
749 | |||
750 | acpi_os_unmap_memory(einj_param, size); | ||
751 | } | ||
758 | einj_exec_ctx_init(&ctx); | 752 | einj_exec_ctx_init(&ctx); |
759 | apei_exec_post_unmap_gars(&ctx); | 753 | apei_exec_post_unmap_gars(&ctx); |
760 | apei_resources_release(&einj_resources); | 754 | apei_resources_release(&einj_resources); |