aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2005-09-12 12:49:24 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-12 13:49:56 -0400
commit673242c10d535bfe238d9d8e82ac93432d35b88e (patch)
tree959b4ffb0ebf788df812fe27498248c26610d22c
parenta54e678b8f476d6f28e6aa4409f6b88ce476af1b (diff)
[PATCH] x86-64: Make lockless machine check record passing a bit more robust.
One machine is constantly throwing NMI watchdog timeouts in mce_log This was one attempt to fix it. (AK: this doesn't actually fix the bug I'm seeing unfortunately, probably drop. I don't like it that the reader can spin forever now waiting for a writer) Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--arch/x86_64/kernel/mce.c32
1 files changed, 21 insertions, 11 deletions
diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c
index 8aa56736cde3..87ea8fdd43fd 100644
--- a/arch/x86_64/kernel/mce.c
+++ b/arch/x86_64/kernel/mce.c
@@ -56,15 +56,19 @@ void mce_log(struct mce *mce)
56 smp_wmb(); 56 smp_wmb();
57 for (;;) { 57 for (;;) {
58 entry = rcu_dereference(mcelog.next); 58 entry = rcu_dereference(mcelog.next);
59 /* When the buffer fills up discard new entries. Assume 59 for (;;) {
60 that the earlier errors are the more interesting. */ 60 /* When the buffer fills up discard new entries. Assume
61 if (entry >= MCE_LOG_LEN) { 61 that the earlier errors are the more interesting. */
62 set_bit(MCE_OVERFLOW, &mcelog.flags); 62 if (entry >= MCE_LOG_LEN) {
63 return; 63 set_bit(MCE_OVERFLOW, &mcelog.flags);
64 return;
65 }
66 /* Old left over entry. Skip. */
67 if (mcelog.entry[entry].finished) {
68 entry++;
69 continue;
70 }
64 } 71 }
65 /* Old left over entry. Skip. */
66 if (mcelog.entry[entry].finished)
67 continue;
68 smp_rmb(); 72 smp_rmb();
69 next = entry + 1; 73 next = entry + 1;
70 if (cmpxchg(&mcelog.next, entry, next) == entry) 74 if (cmpxchg(&mcelog.next, entry, next) == entry)
@@ -404,9 +408,15 @@ static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize, loff
404 } 408 }
405 409
406 err = 0; 410 err = 0;
407 for (i = 0; i < next; i++) { 411 for (i = 0; i < next; i++) {
408 if (!mcelog.entry[i].finished) 412 unsigned long start = jiffies;
409 continue; 413 while (!mcelog.entry[i].finished) {
414 if (!time_before(jiffies, start + 2)) {
415 memset(mcelog.entry + i,0, sizeof(struct mce));
416 continue;
417 }
418 cpu_relax();
419 }
410 smp_rmb(); 420 smp_rmb();
411 err |= copy_to_user(buf, mcelog.entry + i, sizeof(struct mce)); 421 err |= copy_to_user(buf, mcelog.entry + i, sizeof(struct mce));
412 buf += sizeof(struct mce); 422 buf += sizeof(struct mce);