Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ca104edc authored by Chen, Gong's avatar Chen, Gong Committed by Borislav Petkov
Browse files

ACPI, APEI, GHES: Cleanup ghes memory error handling



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: default avatarChen, Gong <gong.chen@linux.intel.com>
Acked-by: default avatarNaveen 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: default avatarBorislav Petkov <bp@suse.de>
parent d3ab3edc
Loading
Loading
Loading
Loading
+20 −16
Original line number Diff line number Diff line
@@ -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)) {
	if (!(mem_err->validation_bits & CPER_MEM_VALID_PA))
		return;

	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
	if (!pfn_valid(pfn)) {
		pr_warn_ratelimited(FW_WARN GHES_PFX
		"Invalid address in generic error data: %#llx\n",
		mem_err->physical_addr);
		return;
	}
	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);
	}

	/* 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
}