diff options
Diffstat (limited to 'drivers/edac/mce_amd.c')
-rw-r--r-- | drivers/edac/mce_amd.c | 62 |
1 files changed, 61 insertions, 1 deletions
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c index 158cd5fa2146..7eb27062f2ef 100644 --- a/drivers/edac/mce_amd.c +++ b/drivers/edac/mce_amd.c | |||
@@ -95,6 +95,23 @@ static const char * const f15h_ic_mce_desc[] = { | |||
95 | "fetch address FIFO" | 95 | "fetch address FIFO" |
96 | }; | 96 | }; |
97 | 97 | ||
98 | static const char * const f15h_cu_mce_desc[] = { | ||
99 | "Fill ECC error on data fills", /* xec = 0x4 */ | ||
100 | "Fill parity error on insn fills", | ||
101 | "Prefetcher request FIFO parity error", | ||
102 | "PRQ address parity error", | ||
103 | "PRQ data parity error", | ||
104 | "WCC Tag ECC error", | ||
105 | "WCC Data ECC error", | ||
106 | "WCB Data parity error", | ||
107 | "VB Data/ECC error", | ||
108 | "L2 Tag ECC error", /* xec = 0x10 */ | ||
109 | "Hard L2 Tag ECC error", | ||
110 | "Multiple hits on L2 tag", | ||
111 | "XAB parity error", | ||
112 | "PRB address parity error" | ||
113 | }; | ||
114 | |||
98 | static bool f12h_dc_mce(u16 ec, u8 xec) | 115 | static bool f12h_dc_mce(u16 ec, u8 xec) |
99 | { | 116 | { |
100 | bool ret = false; | 117 | bool ret = false; |
@@ -405,6 +422,46 @@ wrong_bu_mce: | |||
405 | pr_emerg(HW_ERR "Corrupted BU MCE info?\n"); | 422 | pr_emerg(HW_ERR "Corrupted BU MCE info?\n"); |
406 | } | 423 | } |
407 | 424 | ||
425 | static void amd_decode_cu_mce(struct mce *m) | ||
426 | { | ||
427 | u16 ec = m->status & 0xffff; | ||
428 | u8 xec = (m->status >> 16) & xec_mask; | ||
429 | |||
430 | pr_emerg(HW_ERR "Combined Unit Error: "); | ||
431 | |||
432 | if (TLB_ERROR(ec)) { | ||
433 | if (xec == 0x0) | ||
434 | pr_cont("Data parity TLB read error.\n"); | ||
435 | else if (xec == 0x1) | ||
436 | pr_cont("Poison data provided for TLB fill.\n"); | ||
437 | else | ||
438 | goto wrong_cu_mce; | ||
439 | } else if (BUS_ERROR(ec)) { | ||
440 | if (xec > 2) | ||
441 | goto wrong_cu_mce; | ||
442 | |||
443 | pr_cont("Error during attempted NB data read.\n"); | ||
444 | } else if (MEM_ERROR(ec)) { | ||
445 | switch (xec) { | ||
446 | case 0x4 ... 0xc: | ||
447 | pr_cont("%s.\n", f15h_cu_mce_desc[xec - 0x4]); | ||
448 | break; | ||
449 | |||
450 | case 0x10 ... 0x14: | ||
451 | pr_cont("%s.\n", f15h_cu_mce_desc[xec - 0x7]); | ||
452 | break; | ||
453 | |||
454 | default: | ||
455 | goto wrong_cu_mce; | ||
456 | } | ||
457 | } | ||
458 | |||
459 | return; | ||
460 | |||
461 | wrong_cu_mce: | ||
462 | pr_emerg(HW_ERR "Corrupted CU MCE info?\n"); | ||
463 | } | ||
464 | |||
408 | static void amd_decode_ls_mce(struct mce *m) | 465 | static void amd_decode_ls_mce(struct mce *m) |
409 | { | 466 | { |
410 | u16 ec = m->status & 0xffff; | 467 | u16 ec = m->status & 0xffff; |
@@ -665,7 +722,10 @@ int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data) | |||
665 | break; | 722 | break; |
666 | 723 | ||
667 | case 2: | 724 | case 2: |
668 | amd_decode_bu_mce(m); | 725 | if (boot_cpu_data.x86 == 0x15) |
726 | amd_decode_cu_mce(m); | ||
727 | else | ||
728 | amd_decode_bu_mce(m); | ||
669 | break; | 729 | break; |
670 | 730 | ||
671 | case 3: | 731 | case 3: |