aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);