diff options
author | Huang Ying <ying.huang@intel.com> | 2011-07-13 01:14:28 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2011-08-03 11:15:58 -0400 |
commit | ba61ca4aab47441f1c6cec28a9a6aa0489fd1df3 (patch) | |
tree | 04859a2c04f238b41e535c8e64977aefa99e28d2 /drivers/acpi/apei/ghes.c | |
parent | ea8f5fb8a71fddaf5f3a17100d3247855701f732 (diff) |
ACPI, APEI, GHES: Add hardware memory error recovery support
memory_failure_queue() is called when recoverable memory errors are
notified by firmware to do the recovery work.
Signed-off-by: Huang Ying <ying.huang@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/apei/ghes.c')
-rw-r--r-- | drivers/acpi/apei/ghes.c | 24 |
1 files changed, 17 insertions, 7 deletions
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index 931410d31a9..e92c47c46f9 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c | |||
@@ -451,20 +451,30 @@ static void ghes_clear_estatus(struct ghes *ghes) | |||
451 | 451 | ||
452 | static void ghes_do_proc(const struct acpi_hest_generic_status *estatus) | 452 | static void ghes_do_proc(const struct acpi_hest_generic_status *estatus) |
453 | { | 453 | { |
454 | int sev, processed = 0; | 454 | int sev, sec_sev; |
455 | struct acpi_hest_generic_data *gdata; | 455 | struct acpi_hest_generic_data *gdata; |
456 | 456 | ||
457 | sev = ghes_severity(estatus->error_severity); | 457 | sev = ghes_severity(estatus->error_severity); |
458 | apei_estatus_for_each_section(estatus, gdata) { | 458 | apei_estatus_for_each_section(estatus, gdata) { |
459 | #ifdef CONFIG_X86_MCE | 459 | sec_sev = ghes_severity(gdata->error_severity); |
460 | if (!uuid_le_cmp(*(uuid_le *)gdata->section_type, | 460 | if (!uuid_le_cmp(*(uuid_le *)gdata->section_type, |
461 | CPER_SEC_PLATFORM_MEM)) { | 461 | CPER_SEC_PLATFORM_MEM)) { |
462 | apei_mce_report_mem_error( | 462 | struct cper_sec_mem_err *mem_err; |
463 | sev == GHES_SEV_CORRECTED, | 463 | mem_err = (struct cper_sec_mem_err *)(gdata+1); |
464 | (struct cper_sec_mem_err *)(gdata+1)); | 464 | #ifdef CONFIG_X86_MCE |
465 | processed = 1; | 465 | apei_mce_report_mem_error(sev == GHES_SEV_CORRECTED, |
466 | } | 466 | mem_err); |
467 | #endif | 467 | #endif |
468 | #ifdef CONFIG_ACPI_APEI_MEMORY_FAILURE | ||
469 | if (sev == GHES_SEV_RECOVERABLE && | ||
470 | sec_sev == GHES_SEV_RECOVERABLE && | ||
471 | mem_err->validation_bits & CPER_MEM_VALID_PHYSICAL_ADDRESS) { | ||
472 | unsigned long pfn; | ||
473 | pfn = mem_err->physical_addr >> PAGE_SHIFT; | ||
474 | memory_failure_queue(pfn, 0, 0); | ||
475 | } | ||
476 | #endif | ||
477 | } | ||
468 | } | 478 | } |
469 | } | 479 | } |
470 | 480 | ||