diff options
author | Borislav Petkov <borislav.petkov@amd.com> | 2009-07-27 10:21:14 -0400 |
---|---|---|
committer | Borislav Petkov <borislav.petkov@amd.com> | 2009-09-14 13:01:07 -0400 |
commit | b69b29de65fe4078b125acc9dea34be82f7c362c (patch) | |
tree | 89c4369f9b04e2200e1ef83ed6497fcf150d2d8b /drivers/edac/edac_mce_amd.c | |
parent | 549d042df240dfb4203bab40ad44f9336751b7d6 (diff) |
EDAC, AMD: carve out MCi_STATUS decoding
The MCi_STATUS registers have most field definitions in common so decode
them in the general path. Do not pass ecc_type along and compute it in
__amd64_decode_bus_error instead.
Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
Diffstat (limited to 'drivers/edac/edac_mce_amd.c')
-rw-r--r-- | drivers/edac/edac_mce_amd.c | 57 |
1 files changed, 28 insertions, 29 deletions
diff --git a/drivers/edac/edac_mce_amd.c b/drivers/edac/edac_mce_amd.c index 444c2cc4472d..0ba92d65db43 100644 --- a/drivers/edac/edac_mce_amd.c +++ b/drivers/edac/edac_mce_amd.c | |||
@@ -2,7 +2,7 @@ | |||
2 | #include "edac_mce_amd.h" | 2 | #include "edac_mce_amd.h" |
3 | 3 | ||
4 | static bool report_gart_errors; | 4 | static bool report_gart_errors; |
5 | static void (*nb_bus_decoder)(int node_id, struct err_regs *regs, int ecc_type); | 5 | static void (*nb_bus_decoder)(int node_id, struct err_regs *regs); |
6 | 6 | ||
7 | void amd_report_gart_errors(bool v) | 7 | void amd_report_gart_errors(bool v) |
8 | { | 8 | { |
@@ -10,13 +10,13 @@ void amd_report_gart_errors(bool v) | |||
10 | } | 10 | } |
11 | EXPORT_SYMBOL_GPL(amd_report_gart_errors); | 11 | EXPORT_SYMBOL_GPL(amd_report_gart_errors); |
12 | 12 | ||
13 | void amd_register_ecc_decoder(void (*f)(int, struct err_regs *, int)) | 13 | void amd_register_ecc_decoder(void (*f)(int, struct err_regs *)) |
14 | { | 14 | { |
15 | nb_bus_decoder = f; | 15 | nb_bus_decoder = f; |
16 | } | 16 | } |
17 | EXPORT_SYMBOL_GPL(amd_register_ecc_decoder); | 17 | EXPORT_SYMBOL_GPL(amd_register_ecc_decoder); |
18 | 18 | ||
19 | void amd_unregister_ecc_decoder(void (*f)(int, struct err_regs *, int)) | 19 | void amd_unregister_ecc_decoder(void (*f)(int, struct err_regs *)) |
20 | { | 20 | { |
21 | if (nb_bus_decoder) { | 21 | if (nb_bus_decoder) { |
22 | WARN_ON(nb_bus_decoder != f); | 22 | WARN_ON(nb_bus_decoder != f); |
@@ -130,7 +130,6 @@ EXPORT_SYMBOL_GPL(ext_msgs); | |||
130 | 130 | ||
131 | void amd_decode_nb_mce(int node_id, struct err_regs *regs, int handle_errors) | 131 | void amd_decode_nb_mce(int node_id, struct err_regs *regs, int handle_errors) |
132 | { | 132 | { |
133 | int ecc; | ||
134 | u32 ec = ERROR_CODE(regs->nbsl); | 133 | u32 ec = ERROR_CODE(regs->nbsl); |
135 | u32 xec = EXT_ERROR_CODE(regs->nbsl); | 134 | u32 xec = EXT_ERROR_CODE(regs->nbsl); |
136 | 135 | ||
@@ -151,21 +150,6 @@ void amd_decode_nb_mce(int node_id, struct err_regs *regs, int handle_errors) | |||
151 | pr_cont(", core: %d\n", ilog2((regs->nbsh & 0xf))); | 150 | pr_cont(", core: %d\n", ilog2((regs->nbsh & 0xf))); |
152 | } | 151 | } |
153 | 152 | ||
154 | pr_emerg(" Error: %sorrected", | ||
155 | ((regs->nbsh & K8_NBSH_UC_ERR) ? "Unc" : "C")); | ||
156 | pr_cont(", Report Error: %s", | ||
157 | ((regs->nbsh & K8_NBSH_ERR_EN) ? "yes" : "no")); | ||
158 | pr_cont(", MiscV: %svalid, CPU context corrupt: %s", | ||
159 | ((regs->nbsh & K8_NBSH_MISCV) ? "" : "In"), | ||
160 | ((regs->nbsh & K8_NBSH_PCC) ? "yes" : "no")); | ||
161 | |||
162 | /* do the two bits[14:13] together */ | ||
163 | ecc = regs->nbsh & (0x3 << 13); | ||
164 | if (ecc) | ||
165 | pr_cont(", %sECC Error", ((ecc == 2) ? "C" : "U")); | ||
166 | |||
167 | pr_cont("\n"); | ||
168 | |||
169 | if (TLB_ERROR(ec)) { | 153 | if (TLB_ERROR(ec)) { |
170 | /* | 154 | /* |
171 | * GART errors are intended to help graphics driver developers | 155 | * GART errors are intended to help graphics driver developers |
@@ -191,7 +175,7 @@ void amd_decode_nb_mce(int node_id, struct err_regs *regs, int handle_errors) | |||
191 | } else if (BUS_ERROR(ec)) { | 175 | } else if (BUS_ERROR(ec)) { |
192 | pr_emerg(" Bus (Link/DRAM) error\n"); | 176 | pr_emerg(" Bus (Link/DRAM) error\n"); |
193 | if (nb_bus_decoder) | 177 | if (nb_bus_decoder) |
194 | nb_bus_decoder(node_id, regs, ecc); | 178 | nb_bus_decoder(node_id, regs); |
195 | } else { | 179 | } else { |
196 | /* shouldn't reach here! */ | 180 | /* shouldn't reach here! */ |
197 | pr_warning("%s: unknown MCE error 0x%x\n", __func__, ec); | 181 | pr_warning("%s: unknown MCE error 0x%x\n", __func__, ec); |
@@ -204,16 +188,31 @@ EXPORT_SYMBOL_GPL(amd_decode_nb_mce); | |||
204 | void decode_mce(struct mce *m) | 188 | void decode_mce(struct mce *m) |
205 | { | 189 | { |
206 | struct err_regs regs; | 190 | struct err_regs regs; |
207 | int node; | 191 | int node, ecc; |
208 | 192 | ||
209 | if (m->bank != 4) | 193 | pr_emerg("MC%d_STATUS:\n", m->bank); |
210 | return; | ||
211 | 194 | ||
212 | regs.nbsl = (u32) m->status; | 195 | pr_emerg(" Error: %sorrected, Report: %s, MiscV: %svalid, " |
213 | regs.nbsh = (u32)(m->status >> 32); | 196 | "CPU context corrupt: %s", |
214 | regs.nbeal = (u32) m->addr; | 197 | ((m->status & MCI_STATUS_UC) ? "Unc" : "C"), |
215 | regs.nbeah = (u32)(m->addr >> 32); | 198 | ((m->status & MCI_STATUS_EN) ? "yes" : "no"), |
216 | node = topology_cpu_node_id(m->extcpu); | 199 | ((m->status & MCI_STATUS_MISCV) ? "" : "in"), |
200 | ((m->status & MCI_STATUS_PCC) ? "yes" : "no")); | ||
217 | 201 | ||
218 | amd_decode_nb_mce(node, ®s, 1); | 202 | /* do the two bits[14:13] together */ |
203 | ecc = m->status & (3ULL << 45); | ||
204 | if (ecc) | ||
205 | pr_cont(", %sECC Error", ((ecc == 2) ? "C" : "U")); | ||
206 | |||
207 | pr_cont("\n"); | ||
208 | |||
209 | if (m->bank == 4) { | ||
210 | regs.nbsl = (u32) m->status; | ||
211 | regs.nbsh = (u32)(m->status >> 32); | ||
212 | regs.nbeal = (u32) m->addr; | ||
213 | regs.nbeah = (u32)(m->addr >> 32); | ||
214 | node = per_cpu(cpu_llc_id, m->extcpu); | ||
215 | |||
216 | amd_decode_nb_mce(node, ®s, 1); | ||
217 | } | ||
219 | } | 218 | } |