diff options
author | Ingo Molnar <mingo@elte.hu> | 2011-12-15 02:13:40 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2011-12-15 02:13:40 -0500 |
commit | 715a43182a20a9e2bae59b4e0826a91ee30f355c (patch) | |
tree | 3757a7cd5231a6d4ee4728b60e6a3ed6ee2ce06e /arch/x86/kernel | |
parent | 29e9bf1841e4f9df13b4992a716fece7087dd237 (diff) | |
parent | 0937195715713b37ec843f28d99930dd7b1e8fbe (diff) |
Merge branch 'early-mce-decode' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp into x86/mce
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce.c | 64 |
1 files changed, 57 insertions, 7 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 2af127d4c3d1..5be2464cce6a 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c | |||
@@ -95,13 +95,6 @@ static DECLARE_WAIT_QUEUE_HEAD(mce_chrdev_wait); | |||
95 | static DEFINE_PER_CPU(struct mce, mces_seen); | 95 | static DEFINE_PER_CPU(struct mce, mces_seen); |
96 | static int cpu_missing; | 96 | static int cpu_missing; |
97 | 97 | ||
98 | /* | ||
99 | * CPU/chipset specific EDAC code can register a notifier call here to print | ||
100 | * MCE errors in a human-readable form. | ||
101 | */ | ||
102 | ATOMIC_NOTIFIER_HEAD(x86_mce_decoder_chain); | ||
103 | EXPORT_SYMBOL_GPL(x86_mce_decoder_chain); | ||
104 | |||
105 | /* MCA banks polled by the period polling timer for corrected events */ | 98 | /* MCA banks polled by the period polling timer for corrected events */ |
106 | DEFINE_PER_CPU(mce_banks_t, mce_poll_banks) = { | 99 | DEFINE_PER_CPU(mce_banks_t, mce_poll_banks) = { |
107 | [0 ... BITS_TO_LONGS(MAX_NR_BANKS)-1] = ~0UL | 100 | [0 ... BITS_TO_LONGS(MAX_NR_BANKS)-1] = ~0UL |
@@ -109,6 +102,12 @@ DEFINE_PER_CPU(mce_banks_t, mce_poll_banks) = { | |||
109 | 102 | ||
110 | static DEFINE_PER_CPU(struct work_struct, mce_work); | 103 | static DEFINE_PER_CPU(struct work_struct, mce_work); |
111 | 104 | ||
105 | /* | ||
106 | * CPU/chipset specific EDAC code can register a notifier call here to print | ||
107 | * MCE errors in a human-readable form. | ||
108 | */ | ||
109 | ATOMIC_NOTIFIER_HEAD(x86_mce_decoder_chain); | ||
110 | |||
112 | /* Do initial initialization of a struct mce */ | 111 | /* Do initial initialization of a struct mce */ |
113 | void mce_setup(struct mce *m) | 112 | void mce_setup(struct mce *m) |
114 | { | 113 | { |
@@ -190,6 +189,57 @@ void mce_log(struct mce *mce) | |||
190 | set_bit(0, &mce_need_notify); | 189 | set_bit(0, &mce_need_notify); |
191 | } | 190 | } |
192 | 191 | ||
192 | static void drain_mcelog_buffer(void) | ||
193 | { | ||
194 | unsigned int next, i, prev = 0; | ||
195 | |||
196 | next = rcu_dereference_check_mce(mcelog.next); | ||
197 | |||
198 | do { | ||
199 | struct mce *m; | ||
200 | |||
201 | /* drain what was logged during boot */ | ||
202 | for (i = prev; i < next; i++) { | ||
203 | unsigned long start = jiffies; | ||
204 | unsigned retries = 1; | ||
205 | |||
206 | m = &mcelog.entry[i]; | ||
207 | |||
208 | while (!m->finished) { | ||
209 | if (time_after_eq(jiffies, start + 2*retries)) | ||
210 | retries++; | ||
211 | |||
212 | cpu_relax(); | ||
213 | |||
214 | if (!m->finished && retries >= 4) { | ||
215 | pr_err("MCE: skipping error being logged currently!\n"); | ||
216 | break; | ||
217 | } | ||
218 | } | ||
219 | smp_rmb(); | ||
220 | atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, m); | ||
221 | } | ||
222 | |||
223 | memset(mcelog.entry + prev, 0, (next - prev) * sizeof(*m)); | ||
224 | prev = next; | ||
225 | next = cmpxchg(&mcelog.next, prev, 0); | ||
226 | } while (next != prev); | ||
227 | } | ||
228 | |||
229 | |||
230 | void mce_register_decode_chain(struct notifier_block *nb) | ||
231 | { | ||
232 | atomic_notifier_chain_register(&x86_mce_decoder_chain, nb); | ||
233 | drain_mcelog_buffer(); | ||
234 | } | ||
235 | EXPORT_SYMBOL_GPL(mce_register_decode_chain); | ||
236 | |||
237 | void mce_unregister_decode_chain(struct notifier_block *nb) | ||
238 | { | ||
239 | atomic_notifier_chain_unregister(&x86_mce_decoder_chain, nb); | ||
240 | } | ||
241 | EXPORT_SYMBOL_GPL(mce_unregister_decode_chain); | ||
242 | |||
193 | static void print_mce(struct mce *m) | 243 | static void print_mce(struct mce *m) |
194 | { | 244 | { |
195 | int ret = 0; | 245 | int ret = 0; |