aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/apei
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2014-01-12 11:56:54 -0500
committerIngo Molnar <mingo@kernel.org>2014-01-12 11:56:54 -0500
commitb769e014f3ae4af8a56c6327077b3c40410dedad (patch)
treebeeaa315d7287b96f2813d8d060c43f2658a07b8 /drivers/acpi/apei
parentda4540757d35a98a350d6e8d882a64b2d04f8581 (diff)
parent4f75d8412792777a314ac5c1393a9ed43d695fd1 (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.c4
-rw-r--r--drivers/acpi/apei/einj.c19
-rw-r--r--drivers/acpi/apei/erst.c2
-rw-r--r--drivers/acpi/apei/ghes.c39
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(&reg->address);
571 memcpy(paddr, &reg->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,
216static void *einj_get_parameter_address(void) 217static 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 }