diff options
Diffstat (limited to 'drivers/acpi/apei')
-rw-r--r-- | drivers/acpi/apei/Kconfig | 2 | ||||
-rw-r--r-- | drivers/acpi/apei/apei-base.c | 21 | ||||
-rw-r--r-- | drivers/acpi/apei/einj.c | 4 | ||||
-rw-r--r-- | drivers/acpi/apei/erst-dbg.c | 18 | ||||
-rw-r--r-- | drivers/acpi/apei/erst.c | 29 | ||||
-rw-r--r-- | drivers/acpi/apei/ghes.c | 2 | ||||
-rw-r--r-- | drivers/acpi/apei/hest.c | 11 |
7 files changed, 63 insertions, 24 deletions
diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig index 907e350f1c7d..fca34ccfd294 100644 --- a/drivers/acpi/apei/Kconfig +++ b/drivers/acpi/apei/Kconfig | |||
@@ -34,6 +34,6 @@ config ACPI_APEI_ERST_DEBUG | |||
34 | depends on ACPI_APEI | 34 | depends on ACPI_APEI |
35 | help | 35 | help |
36 | ERST is a way provided by APEI to save and retrieve hardware | 36 | ERST is a way provided by APEI to save and retrieve hardware |
37 | error infomation to and from a persistent store. Enable this | 37 | error information to and from a persistent store. Enable this |
38 | if you want to debugging and testing the ERST kernel support | 38 | if you want to debugging and testing the ERST kernel support |
39 | and firmware implementation. | 39 | and firmware implementation. |
diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c index 73fd0c7487c1..4a904a4bf05f 100644 --- a/drivers/acpi/apei/apei-base.c +++ b/drivers/acpi/apei/apei-base.c | |||
@@ -445,11 +445,15 @@ EXPORT_SYMBOL_GPL(apei_resources_sub); | |||
445 | int apei_resources_request(struct apei_resources *resources, | 445 | int apei_resources_request(struct apei_resources *resources, |
446 | const char *desc) | 446 | const char *desc) |
447 | { | 447 | { |
448 | struct apei_res *res, *res_bak; | 448 | struct apei_res *res, *res_bak = NULL; |
449 | struct resource *r; | 449 | struct resource *r; |
450 | int rc; | ||
450 | 451 | ||
451 | apei_resources_sub(resources, &apei_resources_all); | 452 | rc = apei_resources_sub(resources, &apei_resources_all); |
453 | if (rc) | ||
454 | return rc; | ||
452 | 455 | ||
456 | rc = -EINVAL; | ||
453 | list_for_each_entry(res, &resources->iomem, list) { | 457 | list_for_each_entry(res, &resources->iomem, list) { |
454 | r = request_mem_region(res->start, res->end - res->start, | 458 | r = request_mem_region(res->start, res->end - res->start, |
455 | desc); | 459 | desc); |
@@ -475,7 +479,11 @@ int apei_resources_request(struct apei_resources *resources, | |||
475 | } | 479 | } |
476 | } | 480 | } |
477 | 481 | ||
478 | apei_resources_merge(&apei_resources_all, resources); | 482 | rc = apei_resources_merge(&apei_resources_all, resources); |
483 | if (rc) { | ||
484 | pr_err(APEI_PFX "Fail to merge resources!\n"); | ||
485 | goto err_unmap_ioport; | ||
486 | } | ||
479 | 487 | ||
480 | return 0; | 488 | return 0; |
481 | err_unmap_ioport: | 489 | err_unmap_ioport: |
@@ -491,12 +499,13 @@ err_unmap_iomem: | |||
491 | break; | 499 | break; |
492 | release_mem_region(res->start, res->end - res->start); | 500 | release_mem_region(res->start, res->end - res->start); |
493 | } | 501 | } |
494 | return -EINVAL; | 502 | return rc; |
495 | } | 503 | } |
496 | EXPORT_SYMBOL_GPL(apei_resources_request); | 504 | EXPORT_SYMBOL_GPL(apei_resources_request); |
497 | 505 | ||
498 | void apei_resources_release(struct apei_resources *resources) | 506 | void apei_resources_release(struct apei_resources *resources) |
499 | { | 507 | { |
508 | int rc; | ||
500 | struct apei_res *res; | 509 | struct apei_res *res; |
501 | 510 | ||
502 | list_for_each_entry(res, &resources->iomem, list) | 511 | list_for_each_entry(res, &resources->iomem, list) |
@@ -504,7 +513,9 @@ void apei_resources_release(struct apei_resources *resources) | |||
504 | list_for_each_entry(res, &resources->ioport, list) | 513 | list_for_each_entry(res, &resources->ioport, list) |
505 | release_region(res->start, res->end - res->start); | 514 | release_region(res->start, res->end - res->start); |
506 | 515 | ||
507 | apei_resources_sub(&apei_resources_all, resources); | 516 | rc = apei_resources_sub(&apei_resources_all, resources); |
517 | if (rc) | ||
518 | pr_err(APEI_PFX "Fail to sub resources!\n"); | ||
508 | } | 519 | } |
509 | EXPORT_SYMBOL_GPL(apei_resources_release); | 520 | EXPORT_SYMBOL_GPL(apei_resources_release); |
510 | 521 | ||
diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c index 465c885938ee..cf29df69380b 100644 --- a/drivers/acpi/apei/einj.c +++ b/drivers/acpi/apei/einj.c | |||
@@ -426,7 +426,9 @@ DEFINE_SIMPLE_ATTRIBUTE(error_inject_fops, NULL, | |||
426 | 426 | ||
427 | static int einj_check_table(struct acpi_table_einj *einj_tab) | 427 | static int einj_check_table(struct acpi_table_einj *einj_tab) |
428 | { | 428 | { |
429 | if (einj_tab->header_length != sizeof(struct acpi_table_einj)) | 429 | if ((einj_tab->header_length != |
430 | (sizeof(struct acpi_table_einj) - sizeof(einj_tab->header))) | ||
431 | && (einj_tab->header_length != sizeof(struct acpi_table_einj))) | ||
430 | return -EINVAL; | 432 | return -EINVAL; |
431 | if (einj_tab->header.length < sizeof(struct acpi_table_einj)) | 433 | if (einj_tab->header.length < sizeof(struct acpi_table_einj)) |
432 | return -EINVAL; | 434 | return -EINVAL; |
diff --git a/drivers/acpi/apei/erst-dbg.c b/drivers/acpi/apei/erst-dbg.c index 5281ddda2777..da1228a9a544 100644 --- a/drivers/acpi/apei/erst-dbg.c +++ b/drivers/acpi/apei/erst-dbg.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * APEI Error Record Serialization Table debug support | 2 | * APEI Error Record Serialization Table debug support |
3 | * | 3 | * |
4 | * ERST is a way provided by APEI to save and retrieve hardware error | 4 | * ERST is a way provided by APEI to save and retrieve hardware error |
5 | * infomation to and from a persistent store. This file provide the | 5 | * information to and from a persistent store. This file provide the |
6 | * debugging/testing support for ERST kernel support and firmware | 6 | * debugging/testing support for ERST kernel support and firmware |
7 | * implementation. | 7 | * implementation. |
8 | * | 8 | * |
@@ -111,11 +111,13 @@ retry: | |||
111 | goto out; | 111 | goto out; |
112 | } | 112 | } |
113 | if (len > erst_dbg_buf_len) { | 113 | if (len > erst_dbg_buf_len) { |
114 | kfree(erst_dbg_buf); | 114 | void *p; |
115 | rc = -ENOMEM; | 115 | rc = -ENOMEM; |
116 | erst_dbg_buf = kmalloc(len, GFP_KERNEL); | 116 | p = kmalloc(len, GFP_KERNEL); |
117 | if (!erst_dbg_buf) | 117 | if (!p) |
118 | goto out; | 118 | goto out; |
119 | kfree(erst_dbg_buf); | ||
120 | erst_dbg_buf = p; | ||
119 | erst_dbg_buf_len = len; | 121 | erst_dbg_buf_len = len; |
120 | goto retry; | 122 | goto retry; |
121 | } | 123 | } |
@@ -150,11 +152,13 @@ static ssize_t erst_dbg_write(struct file *filp, const char __user *ubuf, | |||
150 | if (mutex_lock_interruptible(&erst_dbg_mutex)) | 152 | if (mutex_lock_interruptible(&erst_dbg_mutex)) |
151 | return -EINTR; | 153 | return -EINTR; |
152 | if (usize > erst_dbg_buf_len) { | 154 | if (usize > erst_dbg_buf_len) { |
153 | kfree(erst_dbg_buf); | 155 | void *p; |
154 | rc = -ENOMEM; | 156 | rc = -ENOMEM; |
155 | erst_dbg_buf = kmalloc(usize, GFP_KERNEL); | 157 | p = kmalloc(usize, GFP_KERNEL); |
156 | if (!erst_dbg_buf) | 158 | if (!p) |
157 | goto out; | 159 | goto out; |
160 | kfree(erst_dbg_buf); | ||
161 | erst_dbg_buf = p; | ||
158 | erst_dbg_buf_len = usize; | 162 | erst_dbg_buf_len = usize; |
159 | } | 163 | } |
160 | rc = copy_from_user(erst_dbg_buf, ubuf, usize); | 164 | rc = copy_from_user(erst_dbg_buf, ubuf, usize); |
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c index 18645f4e83cd..1211c03149e8 100644 --- a/drivers/acpi/apei/erst.c +++ b/drivers/acpi/apei/erst.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * APEI Error Record Serialization Table support | 2 | * APEI Error Record Serialization Table support |
3 | * | 3 | * |
4 | * ERST is a way provided by APEI to save and retrieve hardware error | 4 | * ERST is a way provided by APEI to save and retrieve hardware error |
5 | * infomation to and from a persistent store. | 5 | * information to and from a persistent store. |
6 | * | 6 | * |
7 | * For more information about ERST, please refer to ACPI Specification | 7 | * For more information about ERST, please refer to ACPI Specification |
8 | * version 4.0, section 17.4. | 8 | * version 4.0, section 17.4. |
@@ -266,13 +266,30 @@ static int erst_exec_move_data(struct apei_exec_context *ctx, | |||
266 | { | 266 | { |
267 | int rc; | 267 | int rc; |
268 | u64 offset; | 268 | u64 offset; |
269 | void *src, *dst; | ||
270 | |||
271 | /* ioremap does not work in interrupt context */ | ||
272 | if (in_interrupt()) { | ||
273 | pr_warning(ERST_PFX | ||
274 | "MOVE_DATA can not be used in interrupt context"); | ||
275 | return -EBUSY; | ||
276 | } | ||
269 | 277 | ||
270 | rc = __apei_exec_read_register(entry, &offset); | 278 | rc = __apei_exec_read_register(entry, &offset); |
271 | if (rc) | 279 | if (rc) |
272 | return rc; | 280 | return rc; |
273 | memmove((void *)ctx->dst_base + offset, | 281 | |
274 | (void *)ctx->src_base + offset, | 282 | src = ioremap(ctx->src_base + offset, ctx->var2); |
275 | ctx->var2); | 283 | if (!src) |
284 | return -ENOMEM; | ||
285 | dst = ioremap(ctx->dst_base + offset, ctx->var2); | ||
286 | if (!dst) | ||
287 | return -ENOMEM; | ||
288 | |||
289 | memmove(dst, src, ctx->var2); | ||
290 | |||
291 | iounmap(src); | ||
292 | iounmap(dst); | ||
276 | 293 | ||
277 | return 0; | 294 | return 0; |
278 | } | 295 | } |
@@ -750,7 +767,9 @@ __setup("erst_disable", setup_erst_disable); | |||
750 | 767 | ||
751 | static int erst_check_table(struct acpi_table_erst *erst_tab) | 768 | static int erst_check_table(struct acpi_table_erst *erst_tab) |
752 | { | 769 | { |
753 | if (erst_tab->header_length != sizeof(struct acpi_table_erst)) | 770 | if ((erst_tab->header_length != |
771 | (sizeof(struct acpi_table_erst) - sizeof(erst_tab->header))) | ||
772 | && (erst_tab->header_length != sizeof(struct acpi_table_einj))) | ||
754 | return -EINVAL; | 773 | return -EINVAL; |
755 | if (erst_tab->header.length < sizeof(struct acpi_table_erst)) | 774 | if (erst_tab->header.length < sizeof(struct acpi_table_erst)) |
756 | return -EINVAL; | 775 | return -EINVAL; |
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index 385a6059714a..0d505e59214d 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c | |||
@@ -302,7 +302,7 @@ static int __devinit ghes_probe(struct platform_device *ghes_dev) | |||
302 | struct ghes *ghes = NULL; | 302 | struct ghes *ghes = NULL; |
303 | int rc = -EINVAL; | 303 | int rc = -EINVAL; |
304 | 304 | ||
305 | generic = ghes_dev->dev.platform_data; | 305 | generic = *(struct acpi_hest_generic **)ghes_dev->dev.platform_data; |
306 | if (!generic->enabled) | 306 | if (!generic->enabled) |
307 | return -ENODEV; | 307 | return -ENODEV; |
308 | 308 | ||
diff --git a/drivers/acpi/apei/hest.c b/drivers/acpi/apei/hest.c index 343168d18266..1a3508a7fe03 100644 --- a/drivers/acpi/apei/hest.c +++ b/drivers/acpi/apei/hest.c | |||
@@ -137,20 +137,23 @@ static int hest_parse_ghes_count(struct acpi_hest_header *hest_hdr, void *data) | |||
137 | 137 | ||
138 | static int hest_parse_ghes(struct acpi_hest_header *hest_hdr, void *data) | 138 | static int hest_parse_ghes(struct acpi_hest_header *hest_hdr, void *data) |
139 | { | 139 | { |
140 | struct acpi_hest_generic *generic; | ||
141 | struct platform_device *ghes_dev; | 140 | struct platform_device *ghes_dev; |
142 | struct ghes_arr *ghes_arr = data; | 141 | struct ghes_arr *ghes_arr = data; |
143 | int rc; | 142 | int rc; |
144 | 143 | ||
145 | if (hest_hdr->type != ACPI_HEST_TYPE_GENERIC_ERROR) | 144 | if (hest_hdr->type != ACPI_HEST_TYPE_GENERIC_ERROR) |
146 | return 0; | 145 | return 0; |
147 | generic = (struct acpi_hest_generic *)hest_hdr; | 146 | |
148 | if (!generic->enabled) | 147 | if (!((struct acpi_hest_generic *)hest_hdr)->enabled) |
149 | return 0; | 148 | return 0; |
150 | ghes_dev = platform_device_alloc("GHES", hest_hdr->source_id); | 149 | ghes_dev = platform_device_alloc("GHES", hest_hdr->source_id); |
151 | if (!ghes_dev) | 150 | if (!ghes_dev) |
152 | return -ENOMEM; | 151 | return -ENOMEM; |
153 | ghes_dev->dev.platform_data = generic; | 152 | |
153 | rc = platform_device_add_data(ghes_dev, &hest_hdr, sizeof(void *)); | ||
154 | if (rc) | ||
155 | goto err; | ||
156 | |||
154 | rc = platform_device_add(ghes_dev); | 157 | rc = platform_device_add(ghes_dev); |
155 | if (rc) | 158 | if (rc) |
156 | goto err; | 159 | goto err; |