aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorBorislav Petkov <borislav.petkov@amd.com>2009-10-07 07:20:38 -0400
committerIngo Molnar <mingo@elte.hu>2009-10-12 06:24:45 -0400
commitfb2531953fd8855abdcf458459020fd382c5deca (patch)
tree2967323398aba0369bff02225f0e9d4d00db0c35 /arch
parentd93a8f829fe1d2f3002f2c6ddb553d12db420412 (diff)
mce, edac: Use an atomic notifier for MCEs decoding
Add an atomic notifier which ensures proper locking when conveying MCE info to EDAC for decoding. The actual notifier call overrides a default, negative priority notifier. Note: make sure we register the default decoder only once since mcheck_init() runs on each CPU. Signed-off-by: Borislav Petkov <borislav.petkov@amd.com> LKML-Reference: <20091003065752.GA8935@liondog.tnic> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/include/asm/mce.h3
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce.c29
2 files changed, 22 insertions, 10 deletions
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index f1363b72364f..227a72df6441 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -108,6 +108,8 @@ struct mce_log {
108#define K8_MCE_THRESHOLD_BANK_5 (MCE_THRESHOLD_BASE + 5 * 9) 108#define K8_MCE_THRESHOLD_BANK_5 (MCE_THRESHOLD_BASE + 5 * 9)
109#define K8_MCE_THRESHOLD_DRAM_ECC (MCE_THRESHOLD_BANK_4 + 0) 109#define K8_MCE_THRESHOLD_DRAM_ECC (MCE_THRESHOLD_BANK_4 + 0)
110 110
111extern struct atomic_notifier_head x86_mce_decoder_chain;
112
111#ifdef __KERNEL__ 113#ifdef __KERNEL__
112 114
113#include <linux/percpu.h> 115#include <linux/percpu.h>
@@ -213,6 +215,5 @@ extern void (*threshold_cpu_callback)(unsigned long action, unsigned int cpu);
213void intel_init_thermal(struct cpuinfo_x86 *c); 215void intel_init_thermal(struct cpuinfo_x86 *c);
214 216
215void mce_log_therm_throt_event(__u64 status); 217void mce_log_therm_throt_event(__u64 status);
216
217#endif /* __KERNEL__ */ 218#endif /* __KERNEL__ */
218#endif /* _ASM_X86_MCE_H */ 219#endif /* _ASM_X86_MCE_H */
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index b1598a9436d0..15ba9c972d7a 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -85,18 +85,26 @@ static DECLARE_WAIT_QUEUE_HEAD(mce_wait);
85static DEFINE_PER_CPU(struct mce, mces_seen); 85static DEFINE_PER_CPU(struct mce, mces_seen);
86static int cpu_missing; 86static int cpu_missing;
87 87
88static void default_decode_mce(struct mce *m) 88/*
89 * CPU/chipset specific EDAC code can register a notifier call here to print
90 * MCE errors in a human-readable form.
91 */
92ATOMIC_NOTIFIER_HEAD(x86_mce_decoder_chain);
93EXPORT_SYMBOL_GPL(x86_mce_decoder_chain);
94
95static int default_decode_mce(struct notifier_block *nb, unsigned long val,
96 void *data)
89{ 97{
90 pr_emerg("No human readable MCE decoding support on this CPU type.\n"); 98 pr_emerg("No human readable MCE decoding support on this CPU type.\n");
91 pr_emerg("Run the message through 'mcelog --ascii' to decode.\n"); 99 pr_emerg("Run the message through 'mcelog --ascii' to decode.\n");
100
101 return NOTIFY_STOP;
92} 102}
93 103
94/* 104static struct notifier_block mce_dec_nb = {
95 * CPU/chipset specific EDAC code can register a callback here to print 105 .notifier_call = default_decode_mce,
96 * MCE errors in a human-readable form: 106 .priority = -1,
97 */ 107};
98void (*x86_mce_decode_callback)(struct mce *m) = default_decode_mce;
99EXPORT_SYMBOL(x86_mce_decode_callback);
100 108
101/* MCA banks polled by the period polling timer for corrected events */ 109/* MCA banks polled by the period polling timer for corrected events */
102DEFINE_PER_CPU(mce_banks_t, mce_poll_banks) = { 110DEFINE_PER_CPU(mce_banks_t, mce_poll_banks) = {
@@ -204,9 +212,9 @@ static void print_mce(struct mce *m)
204 212
205 /* 213 /*
206 * Print out human-readable details about the MCE error, 214 * Print out human-readable details about the MCE error,
207 * (if the CPU has an implementation for that): 215 * (if the CPU has an implementation for that)
208 */ 216 */
209 x86_mce_decode_callback(m); 217 atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, m);
210} 218}
211 219
212static void print_mce_head(void) 220static void print_mce_head(void)
@@ -1420,6 +1428,9 @@ void __cpuinit mcheck_init(struct cpuinfo_x86 *c)
1420 mce_cpu_features(c); 1428 mce_cpu_features(c);
1421 mce_init_timer(); 1429 mce_init_timer();
1422 INIT_WORK(&__get_cpu_var(mce_work), mce_process_work); 1430 INIT_WORK(&__get_cpu_var(mce_work), mce_process_work);
1431
1432 if (raw_smp_processor_id() == 0)
1433 atomic_notifier_chain_register(&x86_mce_decoder_chain, &mce_dec_nb);
1423} 1434}
1424 1435
1425/* 1436/*