diff options
Diffstat (limited to 'drivers/acpi/apei/einj.c')
-rw-r--r-- | drivers/acpi/apei/einj.c | 95 |
1 files changed, 47 insertions, 48 deletions
diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c index 5b898d4dda99..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,17 +241,17 @@ 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 0; | 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 0; | 249 | return NULL; |
266 | } | 250 | } |
267 | return v4param; | 251 | return v4param; |
268 | } | 252 | } |
269 | 253 | ||
270 | return 0; | 254 | return NULL; |
271 | } | 255 | } |
272 | 256 | ||
273 | /* do sanity check to trigger table */ | 257 | /* do sanity check to trigger table */ |
@@ -276,7 +260,7 @@ static int einj_check_trigger_header(struct acpi_einj_trigger *trigger_tab) | |||
276 | if (trigger_tab->header_size != sizeof(struct acpi_einj_trigger)) | 260 | if (trigger_tab->header_size != sizeof(struct acpi_einj_trigger)) |
277 | return -EINVAL; | 261 | return -EINVAL; |
278 | if (trigger_tab->table_size > PAGE_SIZE || | 262 | if (trigger_tab->table_size > PAGE_SIZE || |
279 | trigger_tab->table_size <= trigger_tab->header_size) | 263 | trigger_tab->table_size < trigger_tab->header_size) |
280 | return -EINVAL; | 264 | return -EINVAL; |
281 | if (trigger_tab->entry_count != | 265 | if (trigger_tab->entry_count != |
282 | (trigger_tab->table_size - trigger_tab->header_size) / | 266 | (trigger_tab->table_size - trigger_tab->header_size) / |
@@ -340,6 +324,11 @@ static int __einj_error_trigger(u64 trigger_paddr, u32 type, | |||
340 | "The trigger error action table is invalid\n"); | 324 | "The trigger error action table is invalid\n"); |
341 | goto out_rel_header; | 325 | goto out_rel_header; |
342 | } | 326 | } |
327 | |||
328 | /* No action structures in the TRIGGER_ERROR table, nothing to do */ | ||
329 | if (!trigger_tab->entry_count) | ||
330 | goto out_rel_header; | ||
331 | |||
343 | rc = -EIO; | 332 | rc = -EIO; |
344 | table_size = trigger_tab->table_size; | 333 | table_size = trigger_tab->table_size; |
345 | r = request_mem_region(trigger_paddr + sizeof(*trigger_tab), | 334 | r = request_mem_region(trigger_paddr + sizeof(*trigger_tab), |
@@ -435,41 +424,41 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2) | |||
435 | if (acpi5) { | 424 | if (acpi5) { |
436 | struct set_error_type_with_address *v5param = einj_param; | 425 | struct set_error_type_with_address *v5param = einj_param; |
437 | 426 | ||
438 | writel(type, &v5param->type); | 427 | v5param->type = type; |
439 | if (type & 0x80000000) { | 428 | if (type & 0x80000000) { |
440 | switch (vendor_flags) { | 429 | switch (vendor_flags) { |
441 | case SETWA_FLAGS_APICID: | 430 | case SETWA_FLAGS_APICID: |
442 | writel(param1, &v5param->apicid); | 431 | v5param->apicid = param1; |
443 | break; | 432 | break; |
444 | case SETWA_FLAGS_MEM: | 433 | case SETWA_FLAGS_MEM: |
445 | writeq(param1, &v5param->memory_address); | 434 | v5param->memory_address = param1; |
446 | writeq(param2, &v5param->memory_address_range); | 435 | v5param->memory_address_range = param2; |
447 | break; | 436 | break; |
448 | case SETWA_FLAGS_PCIE_SBDF: | 437 | case SETWA_FLAGS_PCIE_SBDF: |
449 | writel(param1, &v5param->pcie_sbdf); | 438 | v5param->pcie_sbdf = param1; |
450 | break; | 439 | break; |
451 | } | 440 | } |
452 | writel(vendor_flags, &v5param->flags); | 441 | v5param->flags = vendor_flags; |
453 | } else { | 442 | } else { |
454 | switch (type) { | 443 | switch (type) { |
455 | case ACPI_EINJ_PROCESSOR_CORRECTABLE: | 444 | case ACPI_EINJ_PROCESSOR_CORRECTABLE: |
456 | case ACPI_EINJ_PROCESSOR_UNCORRECTABLE: | 445 | case ACPI_EINJ_PROCESSOR_UNCORRECTABLE: |
457 | case ACPI_EINJ_PROCESSOR_FATAL: | 446 | case ACPI_EINJ_PROCESSOR_FATAL: |
458 | writel(param1, &v5param->apicid); | 447 | v5param->apicid = param1; |
459 | writel(SETWA_FLAGS_APICID, &v5param->flags); | 448 | v5param->flags = SETWA_FLAGS_APICID; |
460 | break; | 449 | break; |
461 | case ACPI_EINJ_MEMORY_CORRECTABLE: | 450 | case ACPI_EINJ_MEMORY_CORRECTABLE: |
462 | case ACPI_EINJ_MEMORY_UNCORRECTABLE: | 451 | case ACPI_EINJ_MEMORY_UNCORRECTABLE: |
463 | case ACPI_EINJ_MEMORY_FATAL: | 452 | case ACPI_EINJ_MEMORY_FATAL: |
464 | writeq(param1, &v5param->memory_address); | 453 | v5param->memory_address = param1; |
465 | writeq(param2, &v5param->memory_address_range); | 454 | v5param->memory_address_range = param2; |
466 | writel(SETWA_FLAGS_MEM, &v5param->flags); | 455 | v5param->flags = SETWA_FLAGS_MEM; |
467 | break; | 456 | break; |
468 | case ACPI_EINJ_PCIX_CORRECTABLE: | 457 | case ACPI_EINJ_PCIX_CORRECTABLE: |
469 | case ACPI_EINJ_PCIX_UNCORRECTABLE: | 458 | case ACPI_EINJ_PCIX_UNCORRECTABLE: |
470 | case ACPI_EINJ_PCIX_FATAL: | 459 | case ACPI_EINJ_PCIX_FATAL: |
471 | writel(param1, &v5param->pcie_sbdf); | 460 | v5param->pcie_sbdf = param1; |
472 | writel(SETWA_FLAGS_PCIE_SBDF, &v5param->flags); | 461 | v5param->flags = SETWA_FLAGS_PCIE_SBDF; |
473 | break; | 462 | break; |
474 | } | 463 | } |
475 | } | 464 | } |
@@ -479,8 +468,8 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2) | |||
479 | return rc; | 468 | return rc; |
480 | if (einj_param) { | 469 | if (einj_param) { |
481 | struct einj_parameter *v4param = einj_param; | 470 | struct einj_parameter *v4param = einj_param; |
482 | writeq(param1, &v4param->param1); | 471 | v4param->param1 = param1; |
483 | writeq(param2, &v4param->param2); | 472 | v4param->param2 = param2; |
484 | } | 473 | } |
485 | } | 474 | } |
486 | rc = apei_exec_run(&ctx, ACPI_EINJ_EXECUTE_OPERATION); | 475 | rc = apei_exec_run(&ctx, ACPI_EINJ_EXECUTE_OPERATION); |
@@ -731,8 +720,13 @@ static int __init einj_init(void) | |||
731 | return 0; | 720 | return 0; |
732 | 721 | ||
733 | err_unmap: | 722 | err_unmap: |
734 | if (einj_param) | 723 | if (einj_param) { |
735 | 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 | } | ||
736 | apei_exec_post_unmap_gars(&ctx); | 730 | apei_exec_post_unmap_gars(&ctx); |
737 | err_release: | 731 | err_release: |
738 | apei_resources_release(&einj_resources); | 732 | apei_resources_release(&einj_resources); |
@@ -748,8 +742,13 @@ static void __exit einj_exit(void) | |||
748 | { | 742 | { |
749 | struct apei_exec_context ctx; | 743 | struct apei_exec_context ctx; |
750 | 744 | ||
751 | if (einj_param) | 745 | if (einj_param) { |
752 | 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 | } | ||
753 | einj_exec_ctx_init(&ctx); | 752 | einj_exec_ctx_init(&ctx); |
754 | apei_exec_post_unmap_gars(&ctx); | 753 | apei_exec_post_unmap_gars(&ctx); |
755 | apei_resources_release(&einj_resources); | 754 | apei_resources_release(&einj_resources); |