diff options
author | Aravind Gopalakrishnan <Aravind.Gopalakrishnan@amd.com> | 2014-07-14 10:58:19 -0400 |
---|---|---|
committer | Borislav Petkov <bp@suse.de> | 2014-07-14 10:58:19 -0400 |
commit | eba4bfb34d45a2219d1d7534905c026eea6fcd49 (patch) | |
tree | 960be93a9c968db06b18b627534a0f1260c232ce /drivers/edac | |
parent | 791b470684c1e99b45adabeda827545eeed042db (diff) |
EDAC, MCE, AMD: Add MCE decoding for F15h M60h
Add decoding logic for new Fam15h model 60h.
Tested using mce_amd_inj module and works fine.
Signed-off-by: Aravind Gopalakrishnan <Aravind.Gopalakrishnan@amd.com>
Link: http://lkml.kernel.org/r/1405098795-4678-1-git-send-email-Aravind.Gopalakrishnan@amd.com
[ Boris: simplify a bit. ]
Signed-off-by: Borislav Petkov <bp@suse.de>
Diffstat (limited to 'drivers/edac')
-rw-r--r-- | drivers/edac/mce_amd.c | 44 |
1 files changed, 40 insertions, 4 deletions
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c index 5f43620d580a..f78c1c54dbd5 100644 --- a/drivers/edac/mce_amd.c +++ b/drivers/edac/mce_amd.c | |||
@@ -78,7 +78,8 @@ static const char * const f15h_mc1_mce_desc[] = { | |||
78 | "uop queue", | 78 | "uop queue", |
79 | "insn buffer", | 79 | "insn buffer", |
80 | "predecode buffer", | 80 | "predecode buffer", |
81 | "fetch address FIFO" | 81 | "fetch address FIFO", |
82 | "dispatch uop queue" | ||
82 | }; | 83 | }; |
83 | 84 | ||
84 | static const char * const f15h_mc2_mce_desc[] = { | 85 | static const char * const f15h_mc2_mce_desc[] = { |
@@ -267,6 +268,12 @@ static bool f15h_mc0_mce(u16 ec, u8 xec) | |||
267 | pr_cont("System Read Data Error.\n"); | 268 | pr_cont("System Read Data Error.\n"); |
268 | else | 269 | else |
269 | pr_cont(" Internal error condition type %d.\n", xec); | 270 | pr_cont(" Internal error condition type %d.\n", xec); |
271 | } else if (INT_ERROR(ec)) { | ||
272 | if (xec <= 0x1f) | ||
273 | pr_cont("Hardware Assert.\n"); | ||
274 | else | ||
275 | ret = false; | ||
276 | |||
270 | } else | 277 | } else |
271 | ret = false; | 278 | ret = false; |
272 | 279 | ||
@@ -373,7 +380,7 @@ static bool f15h_mc1_mce(u16 ec, u8 xec) | |||
373 | pr_cont("%s.\n", f15h_mc1_mce_desc[xec-4]); | 380 | pr_cont("%s.\n", f15h_mc1_mce_desc[xec-4]); |
374 | break; | 381 | break; |
375 | 382 | ||
376 | case 0x11 ... 0x14: | 383 | case 0x11 ... 0x15: |
377 | pr_cont("Decoder %s parity error.\n", f15h_mc1_mce_desc[xec-4]); | 384 | pr_cont("Decoder %s parity error.\n", f15h_mc1_mce_desc[xec-4]); |
378 | break; | 385 | break; |
379 | 386 | ||
@@ -397,10 +404,20 @@ static void decode_mc1_mce(struct mce *m) | |||
397 | bool k8 = (boot_cpu_data.x86 == 0xf && (m->status & BIT_64(58))); | 404 | bool k8 = (boot_cpu_data.x86 == 0xf && (m->status & BIT_64(58))); |
398 | 405 | ||
399 | pr_cont("during %s.\n", (k8 ? "system linefill" : "NB data read")); | 406 | pr_cont("during %s.\n", (k8 ? "system linefill" : "NB data read")); |
407 | } else if (INT_ERROR(ec)) { | ||
408 | if (xec <= 0x3f) | ||
409 | pr_cont("Hardware Assert.\n"); | ||
410 | else | ||
411 | goto wrong_mc1_mce; | ||
400 | } else if (fam_ops->mc1_mce(ec, xec)) | 412 | } else if (fam_ops->mc1_mce(ec, xec)) |
401 | ; | 413 | ; |
402 | else | 414 | else |
403 | pr_emerg(HW_ERR "Corrupted MC1 MCE info?\n"); | 415 | goto wrong_mc1_mce; |
416 | |||
417 | return; | ||
418 | |||
419 | wrong_mc1_mce: | ||
420 | pr_emerg(HW_ERR "Corrupted MC1 MCE info?\n"); | ||
404 | } | 421 | } |
405 | 422 | ||
406 | static bool k8_mc2_mce(u16 ec, u8 xec) | 423 | static bool k8_mc2_mce(u16 ec, u8 xec) |
@@ -468,6 +485,11 @@ static bool f15h_mc2_mce(u16 ec, u8 xec) | |||
468 | default: | 485 | default: |
469 | ret = false; | 486 | ret = false; |
470 | } | 487 | } |
488 | } else if (INT_ERROR(ec)) { | ||
489 | if (xec <= 0x3f) | ||
490 | pr_cont("Hardware Assert.\n"); | ||
491 | else | ||
492 | ret = false; | ||
471 | } | 493 | } |
472 | 494 | ||
473 | return ret; | 495 | return ret; |
@@ -615,6 +637,7 @@ static void decode_mc4_mce(struct mce *m) | |||
615 | static void decode_mc5_mce(struct mce *m) | 637 | static void decode_mc5_mce(struct mce *m) |
616 | { | 638 | { |
617 | struct cpuinfo_x86 *c = &boot_cpu_data; | 639 | struct cpuinfo_x86 *c = &boot_cpu_data; |
640 | u16 ec = EC(m->status); | ||
618 | u8 xec = XEC(m->status, xec_mask); | 641 | u8 xec = XEC(m->status, xec_mask); |
619 | 642 | ||
620 | if (c->x86 == 0xf || c->x86 == 0x11) | 643 | if (c->x86 == 0xf || c->x86 == 0x11) |
@@ -622,6 +645,14 @@ static void decode_mc5_mce(struct mce *m) | |||
622 | 645 | ||
623 | pr_emerg(HW_ERR "MC5 Error: "); | 646 | pr_emerg(HW_ERR "MC5 Error: "); |
624 | 647 | ||
648 | if (INT_ERROR(ec)) { | ||
649 | if (xec <= 0x1f) { | ||
650 | pr_cont("Hardware Assert.\n"); | ||
651 | return; | ||
652 | } else | ||
653 | goto wrong_mc5_mce; | ||
654 | } | ||
655 | |||
625 | if (xec == 0x0 || xec == 0xc) | 656 | if (xec == 0x0 || xec == 0xc) |
626 | pr_cont("%s.\n", mc5_mce_desc[xec]); | 657 | pr_cont("%s.\n", mc5_mce_desc[xec]); |
627 | else if (xec <= 0xd) | 658 | else if (xec <= 0xd) |
@@ -642,6 +673,10 @@ static void decode_mc6_mce(struct mce *m) | |||
642 | pr_emerg(HW_ERR "MC6 Error: "); | 673 | pr_emerg(HW_ERR "MC6 Error: "); |
643 | 674 | ||
644 | switch (xec) { | 675 | switch (xec) { |
676 | case 0x0: | ||
677 | pr_cont("Hardware Assertion"); | ||
678 | break; | ||
679 | |||
645 | case 0x1: | 680 | case 0x1: |
646 | pr_cont("Free List"); | 681 | pr_cont("Free List"); |
647 | break; | 682 | break; |
@@ -857,7 +892,8 @@ static int __init mce_amd_init(void) | |||
857 | break; | 892 | break; |
858 | 893 | ||
859 | case 0x15: | 894 | case 0x15: |
860 | xec_mask = 0x1f; | 895 | xec_mask = c->x86_model == 0x60 ? 0x3f : 0x1f; |
896 | |||
861 | fam_ops->mc0_mce = f15h_mc0_mce; | 897 | fam_ops->mc0_mce = f15h_mc0_mce; |
862 | fam_ops->mc1_mce = f15h_mc1_mce; | 898 | fam_ops->mc1_mce = f15h_mc1_mce; |
863 | fam_ops->mc2_mce = f15h_mc2_mce; | 899 | fam_ops->mc2_mce = f15h_mc2_mce; |