diff options
author | Ingo Molnar <mingo@kernel.org> | 2014-01-12 11:56:54 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2014-01-12 11:56:54 -0500 |
commit | b769e014f3ae4af8a56c6327077b3c40410dedad (patch) | |
tree | beeaa315d7287b96f2813d8d060c43f2658a07b8 /drivers/acpi/apei | |
parent | da4540757d35a98a350d6e8d882a64b2d04f8581 (diff) | |
parent | 4f75d8412792777a314ac5c1393a9ed43d695fd1 (diff) |
Merge tag 'ras_for_3.14_p2' of git://git.kernel.org/pub/scm/linux/kernel/git/ras/ras into x86/ras
Pull RAS updates from Borislav Petkov:
" SCI reporting for other error types not only correctable ones
+ APEI GHES cleanups
+ mce timer fix
"
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'drivers/acpi/apei')
-rw-r--r-- | drivers/acpi/apei/apei-base.c | 4 | ||||
-rw-r--r-- | drivers/acpi/apei/einj.c | 19 | ||||
-rw-r--r-- | drivers/acpi/apei/erst.c | 2 | ||||
-rw-r--r-- | drivers/acpi/apei/ghes.c | 39 |
4 files changed, 33 insertions, 31 deletions
diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c index 6d2c49b86b7f..e55584a072c6 100644 --- a/drivers/acpi/apei/apei-base.c +++ b/drivers/acpi/apei/apei-base.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <linux/rculist.h> | 41 | #include <linux/rculist.h> |
42 | #include <linux/interrupt.h> | 42 | #include <linux/interrupt.h> |
43 | #include <linux/debugfs.h> | 43 | #include <linux/debugfs.h> |
44 | #include <asm/unaligned.h> | ||
44 | 45 | ||
45 | #include "apei-internal.h" | 46 | #include "apei-internal.h" |
46 | 47 | ||
@@ -567,8 +568,7 @@ static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr, | |||
567 | bit_offset = reg->bit_offset; | 568 | bit_offset = reg->bit_offset; |
568 | access_size_code = reg->access_width; | 569 | access_size_code = reg->access_width; |
569 | space_id = reg->space_id; | 570 | space_id = reg->space_id; |
570 | /* Handle possible alignment issues */ | 571 | *paddr = get_unaligned(®->address); |
571 | memcpy(paddr, ®->address, sizeof(*paddr)); | ||
572 | if (!*paddr) { | 572 | if (!*paddr) { |
573 | pr_warning(FW_BUG APEI_PFX | 573 | pr_warning(FW_BUG APEI_PFX |
574 | "Invalid physical address in GAR [0x%llx/%u/%u/%u/%u]\n", | 574 | "Invalid physical address in GAR [0x%llx/%u/%u/%u/%u]\n", |
diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c index c76674e2a01f..7dcc8a824aae 100644 --- a/drivers/acpi/apei/einj.c +++ b/drivers/acpi/apei/einj.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/delay.h> | 34 | #include <linux/delay.h> |
35 | #include <linux/mm.h> | 35 | #include <linux/mm.h> |
36 | #include <acpi/acpi.h> | 36 | #include <acpi/acpi.h> |
37 | #include <asm/unaligned.h> | ||
37 | 38 | ||
38 | #include "apei-internal.h" | 39 | #include "apei-internal.h" |
39 | 40 | ||
@@ -216,7 +217,7 @@ static void check_vendor_extension(u64 paddr, | |||
216 | static void *einj_get_parameter_address(void) | 217 | static void *einj_get_parameter_address(void) |
217 | { | 218 | { |
218 | int i; | 219 | int i; |
219 | u64 paddrv4 = 0, paddrv5 = 0; | 220 | u64 pa_v4 = 0, pa_v5 = 0; |
220 | struct acpi_whea_header *entry; | 221 | struct acpi_whea_header *entry; |
221 | 222 | ||
222 | entry = EINJ_TAB_ENTRY(einj_tab); | 223 | entry = EINJ_TAB_ENTRY(einj_tab); |
@@ -225,30 +226,28 @@ static void *einj_get_parameter_address(void) | |||
225 | entry->instruction == ACPI_EINJ_WRITE_REGISTER && | 226 | entry->instruction == ACPI_EINJ_WRITE_REGISTER && |
226 | entry->register_region.space_id == | 227 | entry->register_region.space_id == |
227 | ACPI_ADR_SPACE_SYSTEM_MEMORY) | 228 | ACPI_ADR_SPACE_SYSTEM_MEMORY) |
228 | memcpy(&paddrv4, &entry->register_region.address, | 229 | pa_v4 = get_unaligned(&entry->register_region.address); |
229 | sizeof(paddrv4)); | ||
230 | if (entry->action == ACPI_EINJ_SET_ERROR_TYPE_WITH_ADDRESS && | 230 | if (entry->action == ACPI_EINJ_SET_ERROR_TYPE_WITH_ADDRESS && |
231 | entry->instruction == ACPI_EINJ_WRITE_REGISTER && | 231 | entry->instruction == ACPI_EINJ_WRITE_REGISTER && |
232 | entry->register_region.space_id == | 232 | entry->register_region.space_id == |
233 | ACPI_ADR_SPACE_SYSTEM_MEMORY) | 233 | ACPI_ADR_SPACE_SYSTEM_MEMORY) |
234 | memcpy(&paddrv5, &entry->register_region.address, | 234 | pa_v5 = get_unaligned(&entry->register_region.address); |
235 | sizeof(paddrv5)); | ||
236 | entry++; | 235 | entry++; |
237 | } | 236 | } |
238 | if (paddrv5) { | 237 | if (pa_v5) { |
239 | struct set_error_type_with_address *v5param; | 238 | struct set_error_type_with_address *v5param; |
240 | 239 | ||
241 | v5param = acpi_os_map_memory(paddrv5, sizeof(*v5param)); | 240 | v5param = acpi_os_map_memory(pa_v5, sizeof(*v5param)); |
242 | if (v5param) { | 241 | if (v5param) { |
243 | acpi5 = 1; | 242 | acpi5 = 1; |
244 | check_vendor_extension(paddrv5, v5param); | 243 | check_vendor_extension(pa_v5, v5param); |
245 | return v5param; | 244 | return v5param; |
246 | } | 245 | } |
247 | } | 246 | } |
248 | if (param_extension && paddrv4) { | 247 | if (param_extension && pa_v4) { |
249 | struct einj_parameter *v4param; | 248 | struct einj_parameter *v4param; |
250 | 249 | ||
251 | v4param = acpi_os_map_memory(paddrv4, sizeof(*v4param)); | 250 | v4param = acpi_os_map_memory(pa_v4, sizeof(*v4param)); |
252 | if (!v4param) | 251 | if (!v4param) |
253 | return NULL; | 252 | return NULL; |
254 | if (v4param->reserved1 || v4param->reserved2) { | 253 | if (v4param->reserved1 || v4param->reserved2) { |
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c index cb1d557fc22c..ed65e9c4b5b0 100644 --- a/drivers/acpi/apei/erst.c +++ b/drivers/acpi/apei/erst.c | |||
@@ -611,7 +611,7 @@ static void __erst_record_id_cache_compact(void) | |||
611 | if (entries[i] == APEI_ERST_INVALID_RECORD_ID) | 611 | if (entries[i] == APEI_ERST_INVALID_RECORD_ID) |
612 | continue; | 612 | continue; |
613 | if (wpos != i) | 613 | if (wpos != i) |
614 | memcpy(&entries[wpos], &entries[i], sizeof(entries[i])); | 614 | entries[wpos] = entries[i]; |
615 | wpos++; | 615 | wpos++; |
616 | } | 616 | } |
617 | erst_record_id_cache.len = wpos; | 617 | erst_record_id_cache.len = wpos; |
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index a30bc313787b..46766ef7ef5d 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c | |||
@@ -413,27 +413,31 @@ static void ghes_handle_memory_failure(struct acpi_generic_data *gdata, int sev) | |||
413 | { | 413 | { |
414 | #ifdef CONFIG_ACPI_APEI_MEMORY_FAILURE | 414 | #ifdef CONFIG_ACPI_APEI_MEMORY_FAILURE |
415 | unsigned long pfn; | 415 | unsigned long pfn; |
416 | int flags = -1; | ||
416 | int sec_sev = ghes_severity(gdata->error_severity); | 417 | int sec_sev = ghes_severity(gdata->error_severity); |
417 | struct cper_sec_mem_err *mem_err; | 418 | struct cper_sec_mem_err *mem_err; |
418 | mem_err = (struct cper_sec_mem_err *)(gdata + 1); | 419 | mem_err = (struct cper_sec_mem_err *)(gdata + 1); |
419 | 420 | ||
420 | if (sec_sev == GHES_SEV_CORRECTED && | 421 | if (!(mem_err->validation_bits & CPER_MEM_VALID_PA)) |
421 | (gdata->flags & CPER_SEC_ERROR_THRESHOLD_EXCEEDED) && | 422 | return; |
422 | (mem_err->validation_bits & CPER_MEM_VALID_PA)) { | 423 | |
423 | pfn = mem_err->physical_addr >> PAGE_SHIFT; | 424 | pfn = mem_err->physical_addr >> PAGE_SHIFT; |
424 | if (pfn_valid(pfn)) | 425 | if (!pfn_valid(pfn)) { |
425 | memory_failure_queue(pfn, 0, MF_SOFT_OFFLINE); | 426 | pr_warn_ratelimited(FW_WARN GHES_PFX |
426 | else if (printk_ratelimit()) | 427 | "Invalid address in generic error data: %#llx\n", |
427 | pr_warn(FW_WARN GHES_PFX | 428 | mem_err->physical_addr); |
428 | "Invalid address in generic error data: %#llx\n", | 429 | return; |
429 | mem_err->physical_addr); | ||
430 | } | ||
431 | if (sev == GHES_SEV_RECOVERABLE && | ||
432 | sec_sev == GHES_SEV_RECOVERABLE && | ||
433 | mem_err->validation_bits & CPER_MEM_VALID_PA) { | ||
434 | pfn = mem_err->physical_addr >> PAGE_SHIFT; | ||
435 | memory_failure_queue(pfn, 0, 0); | ||
436 | } | 430 | } |
431 | |||
432 | /* iff following two events can be handled properly by now */ | ||
433 | if (sec_sev == GHES_SEV_CORRECTED && | ||
434 | (gdata->flags & CPER_SEC_ERROR_THRESHOLD_EXCEEDED)) | ||
435 | flags = MF_SOFT_OFFLINE; | ||
436 | if (sev == GHES_SEV_RECOVERABLE && sec_sev == GHES_SEV_RECOVERABLE) | ||
437 | flags = 0; | ||
438 | |||
439 | if (flags != -1) | ||
440 | memory_failure_queue(pfn, 0, flags); | ||
437 | #endif | 441 | #endif |
438 | } | 442 | } |
439 | 443 | ||
@@ -453,8 +457,7 @@ static void ghes_do_proc(struct ghes *ghes, | |||
453 | ghes_edac_report_mem_error(ghes, sev, mem_err); | 457 | ghes_edac_report_mem_error(ghes, sev, mem_err); |
454 | 458 | ||
455 | #ifdef CONFIG_X86_MCE | 459 | #ifdef CONFIG_X86_MCE |
456 | apei_mce_report_mem_error(sev == GHES_SEV_CORRECTED, | 460 | apei_mce_report_mem_error(sev, mem_err); |
457 | mem_err); | ||
458 | #endif | 461 | #endif |
459 | ghes_handle_memory_failure(gdata, sev); | 462 | ghes_handle_memory_failure(gdata, sev); |
460 | } | 463 | } |