aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJacob Shin <jacob.shin@amd.com>2012-12-18 16:06:10 -0500
committerBorislav Petkov <bp@suse.de>2013-01-22 16:39:54 -0500
commit4a73d3de63d4c4498e3dbf8614604c6b1dcc1fc2 (patch)
treec51ec0b6932c30564d45f6fb29b09da0a40d2a32
parentacc7fcb40067b702d6c80bf8c6f6749a5a06bc91 (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.c56
-rw-r--r--drivers/edac/mce_amd.h1
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
402static void decode_mc2_mce(struct mce *m) 402static 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
444static void decode_f15_mc2_mce(struct mce *m) 438static 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
472static 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
484static void decode_mc3_mce(struct mce *m) 483static 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[];
78struct amd_decoder_ops { 78struct 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
83void amd_report_gart_errors(bool); 84void amd_report_gart_errors(bool);