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 | |
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')
-rw-r--r-- | drivers/acpi/apei/Kconfig | 7 | ||||
-rw-r--r-- | drivers/acpi/apei/ghes.c | 24 |
2 files changed, 24 insertions, 7 deletions
diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig index 35596eaaca17..c34aa51af4ee 100644 --- a/drivers/acpi/apei/Kconfig +++ b/drivers/acpi/apei/Kconfig | |||
@@ -32,6 +32,13 @@ config ACPI_APEI_PCIEAER | |||
32 | PCIe AER errors may be reported via APEI firmware first mode. | 32 | PCIe AER errors may be reported via APEI firmware first mode. |
33 | Turn on this option to enable the corresponding support. | 33 | Turn on this option to enable the corresponding support. |
34 | 34 | ||
35 | config ACPI_APEI_MEMORY_FAILURE | ||
36 | bool "APEI memory error recovering support" | ||
37 | depends on ACPI_APEI && MEMORY_FAILURE | ||
38 | help | ||
39 | Memory errors may be reported via APEI firmware first mode. | ||
40 | Turn on this option to enable the memory recovering support. | ||
41 | |||
35 | config ACPI_APEI_EINJ | 42 | config ACPI_APEI_EINJ |
36 | tristate "APEI Error INJection (EINJ)" | 43 | tristate "APEI Error INJection (EINJ)" |
37 | depends on ACPI_APEI && DEBUG_FS | 44 | depends on ACPI_APEI && DEBUG_FS |
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index 931410d31a96..e92c47c46f91 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 | ||