diff options
author | Jacob Shin <jacob.shin@amd.com> | 2012-12-18 16:06:10 -0500 |
---|---|---|
committer | Borislav Petkov <bp@suse.de> | 2013-01-22 16:39:54 -0500 |
commit | 4a73d3de63d4c4498e3dbf8614604c6b1dcc1fc2 (patch) | |
tree | c51ec0b6932c30564d45f6fb29b09da0a40d2a32 | |
parent | acc7fcb40067b702d6c80bf8c6f6749a5a06bc91 (diff) |
EDAC, MCE, AMD: Make MC2 decoding per-family
Currently only AMD Family 15h processors have special handling for MC2
errors. Since upcoming Family 16h will also need unique handling, let's
make MC2 handling part of amd_decoder_ops.
Signed-off-by: Jacob Shin <jacob.shin@amd.com>
Signed-off-by: Borislav Petkov <bp@alien8.de>
-rw-r--r-- | drivers/edac/mce_amd.c | 56 | ||||
-rw-r--r-- | drivers/edac/mce_amd.h | 1 |
2 files changed, 30 insertions, 27 deletions
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c index ad637572d8c7..e4752bec5023 100644 --- a/drivers/edac/mce_amd.c +++ b/drivers/edac/mce_amd.c | |||
@@ -399,12 +399,9 @@ static void decode_mc1_mce(struct mce *m) | |||
399 | pr_emerg(HW_ERR "Corrupted MC1 MCE info?\n"); | 399 | pr_emerg(HW_ERR "Corrupted MC1 MCE info?\n"); |
400 | } | 400 | } |
401 | 401 | ||
402 | static void decode_mc2_mce(struct mce *m) | 402 | static bool k8_mc2_mce(u16 ec, u8 xec) |
403 | { | 403 | { |
404 | u16 ec = EC(m->status); | 404 | bool ret = true; |
405 | u8 xec = XEC(m->status, xec_mask); | ||
406 | |||
407 | pr_emerg(HW_ERR "MC2 Error"); | ||
408 | 405 | ||
409 | if (xec == 0x1) | 406 | if (xec == 0x1) |
410 | pr_cont(" in the write data buffers.\n"); | 407 | pr_cont(" in the write data buffers.\n"); |
@@ -429,24 +426,18 @@ static void decode_mc2_mce(struct mce *m) | |||
429 | pr_cont(": %s parity/ECC error during data " | 426 | pr_cont(": %s parity/ECC error during data " |
430 | "access from L2.\n", R4_MSG(ec)); | 427 | "access from L2.\n", R4_MSG(ec)); |
431 | else | 428 | else |
432 | goto wrong_mc2_mce; | 429 | ret = false; |
433 | } else | 430 | } else |
434 | goto wrong_mc2_mce; | 431 | ret = false; |
435 | } else | 432 | } else |
436 | goto wrong_mc2_mce; | 433 | ret = false; |
437 | |||
438 | return; | ||
439 | 434 | ||
440 | wrong_mc2_mce: | 435 | return ret; |
441 | pr_emerg(HW_ERR "Corrupted MC2 MCE info?\n"); | ||
442 | } | 436 | } |
443 | 437 | ||
444 | static void decode_f15_mc2_mce(struct mce *m) | 438 | static bool f15h_mc2_mce(u16 ec, u8 xec) |
445 | { | 439 | { |
446 | u16 ec = EC(m->status); | 440 | bool ret = true; |
447 | u8 xec = XEC(m->status, xec_mask); | ||
448 | |||
449 | pr_emerg(HW_ERR "MC2 Error: "); | ||
450 | 441 | ||
451 | if (TLB_ERROR(ec)) { | 442 | if (TLB_ERROR(ec)) { |
452 | if (xec == 0x0) | 443 | if (xec == 0x0) |
@@ -454,10 +445,10 @@ static void decode_f15_mc2_mce(struct mce *m) | |||
454 | else if (xec == 0x1) | 445 | else if (xec == 0x1) |
455 | pr_cont("Poison data provided for TLB fill.\n"); | 446 | pr_cont("Poison data provided for TLB fill.\n"); |
456 | else | 447 | else |
457 | goto wrong_f15_mc2_mce; | 448 | ret = false; |
458 | } else if (BUS_ERROR(ec)) { | 449 | } else if (BUS_ERROR(ec)) { |
459 | if (xec > 2) | 450 | if (xec > 2) |
460 | goto wrong_f15_mc2_mce; | 451 | ret = false; |
461 | 452 | ||
462 | pr_cont("Error during attempted NB data read.\n"); | 453 | pr_cont("Error during attempted NB data read.\n"); |
463 | } else if (MEM_ERROR(ec)) { | 454 | } else if (MEM_ERROR(ec)) { |
@@ -471,14 +462,22 @@ static void decode_f15_mc2_mce(struct mce *m) | |||
471 | break; | 462 | break; |
472 | 463 | ||
473 | default: | 464 | default: |
474 | goto wrong_f15_mc2_mce; | 465 | ret = false; |
475 | } | 466 | } |
476 | } | 467 | } |
477 | 468 | ||
478 | return; | 469 | return ret; |
470 | } | ||
471 | |||
472 | static void decode_mc2_mce(struct mce *m) | ||
473 | { | ||
474 | u16 ec = EC(m->status); | ||
475 | u8 xec = XEC(m->status, xec_mask); | ||
479 | 476 | ||
480 | wrong_f15_mc2_mce: | 477 | pr_emerg(HW_ERR "MC2 Error: "); |
481 | pr_emerg(HW_ERR "Corrupted MC2 MCE info?\n"); | 478 | |
479 | if (!fam_ops->mc2_mce(ec, xec)) | ||
480 | pr_cont(HW_ERR "Corrupted MC2 MCE info?\n"); | ||
482 | } | 481 | } |
483 | 482 | ||
484 | static void decode_mc3_mce(struct mce *m) | 483 | static void decode_mc3_mce(struct mce *m) |
@@ -702,10 +701,7 @@ int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data) | |||
702 | break; | 701 | break; |
703 | 702 | ||
704 | case 2: | 703 | case 2: |
705 | if (c->x86 == 0x15) | 704 | decode_mc2_mce(m); |
706 | decode_f15_mc2_mce(m); | ||
707 | else | ||
708 | decode_mc2_mce(m); | ||
709 | break; | 705 | break; |
710 | 706 | ||
711 | case 3: | 707 | case 3: |
@@ -783,33 +779,39 @@ static int __init mce_amd_init(void) | |||
783 | case 0xf: | 779 | case 0xf: |
784 | fam_ops->mc0_mce = k8_mc0_mce; | 780 | fam_ops->mc0_mce = k8_mc0_mce; |
785 | fam_ops->mc1_mce = k8_mc1_mce; | 781 | fam_ops->mc1_mce = k8_mc1_mce; |
782 | fam_ops->mc2_mce = k8_mc2_mce; | ||
786 | break; | 783 | break; |
787 | 784 | ||
788 | case 0x10: | 785 | case 0x10: |
789 | fam_ops->mc0_mce = f10h_mc0_mce; | 786 | fam_ops->mc0_mce = f10h_mc0_mce; |
790 | fam_ops->mc1_mce = k8_mc1_mce; | 787 | fam_ops->mc1_mce = k8_mc1_mce; |
788 | fam_ops->mc2_mce = k8_mc2_mce; | ||
791 | break; | 789 | break; |
792 | 790 | ||
793 | case 0x11: | 791 | case 0x11: |
794 | fam_ops->mc0_mce = k8_mc0_mce; | 792 | fam_ops->mc0_mce = k8_mc0_mce; |
795 | fam_ops->mc1_mce = k8_mc1_mce; | 793 | fam_ops->mc1_mce = k8_mc1_mce; |
794 | fam_ops->mc2_mce = k8_mc2_mce; | ||
796 | break; | 795 | break; |
797 | 796 | ||
798 | case 0x12: | 797 | case 0x12: |
799 | fam_ops->mc0_mce = f12h_mc0_mce; | 798 | fam_ops->mc0_mce = f12h_mc0_mce; |
800 | fam_ops->mc1_mce = k8_mc1_mce; | 799 | fam_ops->mc1_mce = k8_mc1_mce; |
800 | fam_ops->mc2_mce = k8_mc2_mce; | ||
801 | break; | 801 | break; |
802 | 802 | ||
803 | case 0x14: | 803 | case 0x14: |
804 | nb_err_cpumask = 0x3; | 804 | nb_err_cpumask = 0x3; |
805 | fam_ops->mc0_mce = f14h_mc0_mce; | 805 | fam_ops->mc0_mce = f14h_mc0_mce; |
806 | fam_ops->mc1_mce = f14h_mc1_mce; | 806 | fam_ops->mc1_mce = f14h_mc1_mce; |
807 | fam_ops->mc2_mce = k8_mc2_mce; | ||
807 | break; | 808 | break; |
808 | 809 | ||
809 | case 0x15: | 810 | case 0x15: |
810 | xec_mask = 0x1f; | 811 | xec_mask = 0x1f; |
811 | fam_ops->mc0_mce = f15h_mc0_mce; | 812 | fam_ops->mc0_mce = f15h_mc0_mce; |
812 | fam_ops->mc1_mce = f15h_mc1_mce; | 813 | fam_ops->mc1_mce = f15h_mc1_mce; |
814 | fam_ops->mc2_mce = f15h_mc2_mce; | ||
813 | break; | 815 | break; |
814 | 816 | ||
815 | default: | 817 | default: |
diff --git a/drivers/edac/mce_amd.h b/drivers/edac/mce_amd.h index 679679951e23..000f6e2c4cbe 100644 --- a/drivers/edac/mce_amd.h +++ b/drivers/edac/mce_amd.h | |||
@@ -78,6 +78,7 @@ extern const char * const ii_msgs[]; | |||
78 | struct amd_decoder_ops { | 78 | struct amd_decoder_ops { |
79 | bool (*mc0_mce)(u16, u8); | 79 | bool (*mc0_mce)(u16, u8); |
80 | bool (*mc1_mce)(u16, u8); | 80 | bool (*mc1_mce)(u16, u8); |
81 | bool (*mc2_mce)(u16, u8); | ||
81 | }; | 82 | }; |
82 | 83 | ||
83 | void amd_report_gart_errors(bool); | 84 | void amd_report_gart_errors(bool); |