ACPI, APEI, GHES: Cleanup ghes memory error handling
authorChen, Gong <gong.chen@linux.intel.com>
Mon, 25 Nov 2013 07:15:01 +0000 (02:15 -0500)
committerBorislav Petkov <bp@suse.de>
Sat, 21 Dec 2013 12:35:59 +0000 (13:35 +0100)
Cleanup the logic in ghes_handle_memory_failure(). While at it, add
proper PFN validity check for UC error and cleanup the code logic to
make it simpler and cleaner.

Signed-off-by: Chen, Gong <gong.chen@linux.intel.com>
Acked-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
Link: http://lkml.kernel.org/r/1385363701-12387-2-git-send-email-gong.chen@linux.intel.com
[ Boris: massage commit message. ]
Signed-off-by: Borislav Petkov <bp@suse.de>
drivers/acpi/apei/ghes.c

index ce3683d93a137a25b4ca8e863ed448d6fbc2b7cd..46766ef7ef5de9be5cfa6f95d7f81a6039f9e4ec 100644 (file)
@@ -413,27 +413,31 @@ static void ghes_handle_memory_failure(struct acpi_generic_data *gdata, int sev)
 {
 #ifdef CONFIG_ACPI_APEI_MEMORY_FAILURE
        unsigned long pfn;
+       int flags = -1;
        int sec_sev = ghes_severity(gdata->error_severity);
        struct cper_sec_mem_err *mem_err;
        mem_err = (struct cper_sec_mem_err *)(gdata + 1);
 
-       if (sec_sev == GHES_SEV_CORRECTED &&
-           (gdata->flags & CPER_SEC_ERROR_THRESHOLD_EXCEEDED) &&
-           (mem_err->validation_bits & CPER_MEM_VALID_PA)) {
-               pfn = mem_err->physical_addr >> PAGE_SHIFT;
-               if (pfn_valid(pfn))
-                       memory_failure_queue(pfn, 0, MF_SOFT_OFFLINE);
-               else if (printk_ratelimit())
-                       pr_warn(FW_WARN GHES_PFX
-                       "Invalid address in generic error data: %#llx\n",
-                       mem_err->physical_addr);
-       }
-       if (sev == GHES_SEV_RECOVERABLE &&
-           sec_sev == GHES_SEV_RECOVERABLE &&
-           mem_err->validation_bits & CPER_MEM_VALID_PA) {
-               pfn = mem_err->physical_addr >> PAGE_SHIFT;
-               memory_failure_queue(pfn, 0, 0);
+       if (!(mem_err->validation_bits & CPER_MEM_VALID_PA))
+               return;
+
+       pfn = mem_err->physical_addr >> PAGE_SHIFT;
+       if (!pfn_valid(pfn)) {
+               pr_warn_ratelimited(FW_WARN GHES_PFX
+               "Invalid address in generic error data: %#llx\n",
+               mem_err->physical_addr);
+               return;
        }
+
+       /* iff following two events can be handled properly by now */
+       if (sec_sev == GHES_SEV_CORRECTED &&
+           (gdata->flags & CPER_SEC_ERROR_THRESHOLD_EXCEEDED))
+               flags = MF_SOFT_OFFLINE;
+       if (sev == GHES_SEV_RECOVERABLE && sec_sev == GHES_SEV_RECOVERABLE)
+               flags = 0;
+
+       if (flags != -1)
+               memory_failure_queue(pfn, 0, flags);
 #endif
 }