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>
This commit is contained in:
Jacob Shin 2012-12-18 15:06:10 -06:00 committed by Borislav Petkov
parent acc7fcb400
commit 4a73d3de63
2 changed files with 30 additions and 27 deletions

View File

@ -399,12 +399,9 @@ static void decode_mc1_mce(struct mce *m)
pr_emerg(HW_ERR "Corrupted MC1 MCE info?\n"); pr_emerg(HW_ERR "Corrupted MC1 MCE info?\n");
} }
static void decode_mc2_mce(struct mce *m) static bool k8_mc2_mce(u16 ec, u8 xec)
{ {
u16 ec = EC(m->status); bool ret = true;
u8 xec = XEC(m->status, xec_mask);
pr_emerg(HW_ERR "MC2 Error");
if (xec == 0x1) if (xec == 0x1)
pr_cont(" in the write data buffers.\n"); pr_cont(" in the write data buffers.\n");
@ -429,24 +426,18 @@ static void decode_mc2_mce(struct mce *m)
pr_cont(": %s parity/ECC error during data " pr_cont(": %s parity/ECC error during data "
"access from L2.\n", R4_MSG(ec)); "access from L2.\n", R4_MSG(ec));
else else
goto wrong_mc2_mce; ret = false;
} else } else
goto wrong_mc2_mce; ret = false;
} else } else
goto wrong_mc2_mce; ret = false;
return; return ret;
wrong_mc2_mce:
pr_emerg(HW_ERR "Corrupted MC2 MCE info?\n");
} }
static void decode_f15_mc2_mce(struct mce *m) static bool f15h_mc2_mce(u16 ec, u8 xec)
{ {
u16 ec = EC(m->status); bool ret = true;
u8 xec = XEC(m->status, xec_mask);
pr_emerg(HW_ERR "MC2 Error: ");
if (TLB_ERROR(ec)) { if (TLB_ERROR(ec)) {
if (xec == 0x0) if (xec == 0x0)
@ -454,10 +445,10 @@ static void decode_f15_mc2_mce(struct mce *m)
else if (xec == 0x1) else if (xec == 0x1)
pr_cont("Poison data provided for TLB fill.\n"); pr_cont("Poison data provided for TLB fill.\n");
else else
goto wrong_f15_mc2_mce; ret = false;
} else if (BUS_ERROR(ec)) { } else if (BUS_ERROR(ec)) {
if (xec > 2) if (xec > 2)
goto wrong_f15_mc2_mce; ret = false;
pr_cont("Error during attempted NB data read.\n"); pr_cont("Error during attempted NB data read.\n");
} else if (MEM_ERROR(ec)) { } else if (MEM_ERROR(ec)) {
@ -471,14 +462,22 @@ static void decode_f15_mc2_mce(struct mce *m)
break; break;
default: default:
goto wrong_f15_mc2_mce; ret = false;
} }
} }
return; return ret;
}
wrong_f15_mc2_mce: static void decode_mc2_mce(struct mce *m)
pr_emerg(HW_ERR "Corrupted MC2 MCE info?\n"); {
u16 ec = EC(m->status);
u8 xec = XEC(m->status, xec_mask);
pr_emerg(HW_ERR "MC2 Error: ");
if (!fam_ops->mc2_mce(ec, xec))
pr_cont(HW_ERR "Corrupted MC2 MCE info?\n");
} }
static void decode_mc3_mce(struct mce *m) static void decode_mc3_mce(struct mce *m)
@ -702,9 +701,6 @@ int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
break; break;
case 2: case 2:
if (c->x86 == 0x15)
decode_f15_mc2_mce(m);
else
decode_mc2_mce(m); decode_mc2_mce(m);
break; break;
@ -783,33 +779,39 @@ static int __init mce_amd_init(void)
case 0xf: case 0xf:
fam_ops->mc0_mce = k8_mc0_mce; fam_ops->mc0_mce = k8_mc0_mce;
fam_ops->mc1_mce = k8_mc1_mce; fam_ops->mc1_mce = k8_mc1_mce;
fam_ops->mc2_mce = k8_mc2_mce;
break; break;
case 0x10: case 0x10:
fam_ops->mc0_mce = f10h_mc0_mce; fam_ops->mc0_mce = f10h_mc0_mce;
fam_ops->mc1_mce = k8_mc1_mce; fam_ops->mc1_mce = k8_mc1_mce;
fam_ops->mc2_mce = k8_mc2_mce;
break; break;
case 0x11: case 0x11:
fam_ops->mc0_mce = k8_mc0_mce; fam_ops->mc0_mce = k8_mc0_mce;
fam_ops->mc1_mce = k8_mc1_mce; fam_ops->mc1_mce = k8_mc1_mce;
fam_ops->mc2_mce = k8_mc2_mce;
break; break;
case 0x12: case 0x12:
fam_ops->mc0_mce = f12h_mc0_mce; fam_ops->mc0_mce = f12h_mc0_mce;
fam_ops->mc1_mce = k8_mc1_mce; fam_ops->mc1_mce = k8_mc1_mce;
fam_ops->mc2_mce = k8_mc2_mce;
break; break;
case 0x14: case 0x14:
nb_err_cpumask = 0x3; nb_err_cpumask = 0x3;
fam_ops->mc0_mce = f14h_mc0_mce; fam_ops->mc0_mce = f14h_mc0_mce;
fam_ops->mc1_mce = f14h_mc1_mce; fam_ops->mc1_mce = f14h_mc1_mce;
fam_ops->mc2_mce = k8_mc2_mce;
break; break;
case 0x15: case 0x15:
xec_mask = 0x1f; xec_mask = 0x1f;
fam_ops->mc0_mce = f15h_mc0_mce; fam_ops->mc0_mce = f15h_mc0_mce;
fam_ops->mc1_mce = f15h_mc1_mce; fam_ops->mc1_mce = f15h_mc1_mce;
fam_ops->mc2_mce = f15h_mc2_mce;
break; break;
default: default:

View File

@ -78,6 +78,7 @@ extern const char * const ii_msgs[];
struct amd_decoder_ops { struct amd_decoder_ops {
bool (*mc0_mce)(u16, u8); bool (*mc0_mce)(u16, u8);
bool (*mc1_mce)(u16, u8); bool (*mc1_mce)(u16, u8);
bool (*mc2_mce)(u16, u8);
}; };
void amd_report_gart_errors(bool); void amd_report_gart_errors(bool);