void mce_log(struct mce *mce) { unsigned next, entry; /* Emit the trace record: */ trace_mce_record(mce); mce->finished = 0; wmb(); for (;;) { entry = rcu_dereference_check_mce(mcelog.next); for (;;) { /* * If edac_mce is enabled, it will check the error type * and will process it, if it is a known error. * Otherwise, the error will be sent through mcelog * interface */ if (edac_mce_parse(mce)) return; /* * When the buffer fills up discard new entries. * Assume that the earlier errors are the more * interesting ones: */ if (entry >= MCE_LOG_LEN) { set_bit(MCE_OVERFLOW, (unsigned long *)&mcelog.flags); return; } /* Old left over entry. Skip: */ if (mcelog.entry[entry].finished) { entry++; continue; } break; } smp_rmb(); next = entry + 1; if (cmpxchg(&mcelog.next, entry, next) == entry) break; } memcpy(mcelog.entry + entry, mce, sizeof(struct mce)); wmb(); mcelog.entry[entry].finished = 1; wmb(); mce->finished = 1; set_bit(0, &mce_need_notify); }
void mce_log(struct mce *mce) { unsigned next, entry; int ret = 0; /* Emit the trace record: */ trace_mce_record(mce); ret = atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, mce); if (ret == NOTIFY_STOP) return; mce->finished = 0; wmb(); for (;;) { entry = rcu_dereference_check_mce(mcelog.next); for (;;) { /* * When the buffer fills up discard new entries. * Assume that the earlier errors are the more * interesting ones: */ if (entry >= MCE_LOG_LEN) { set_bit(MCE_OVERFLOW, (unsigned long *)&mcelog.flags); return; } /* Old left over entry. Skip: */ if (mcelog.entry[entry].finished) { entry++; continue; } break; } smp_rmb(); next = entry + 1; if (cmpxchg(&mcelog.next, entry, next) == entry) break; } memcpy(mcelog.entry + entry, mce, sizeof(struct mce)); wmb(); mcelog.entry[entry].finished = 1; wmb(); mce->finished = 1; set_bit(0, &mce_need_notify); }
void mce_log(struct mce *mce) { unsigned next, entry; int ret = 0; trace_mce_record(mce); ret = atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, mce); if (ret == NOTIFY_STOP) return; mce->finished = 0; wmb(); for (;;) { entry = rcu_dereference_check_mce(mcelog.next); for (;;) { if (entry >= MCE_LOG_LEN) { set_bit(MCE_OVERFLOW, (unsigned long *)&mcelog.flags); return; } if (mcelog.entry[entry].finished) { entry++; continue; } break; } smp_rmb(); next = entry + 1; if (cmpxchg(&mcelog.next, entry, next) == entry) break; } memcpy(mcelog.entry + entry, mce, sizeof(struct mce)); wmb(); mcelog.entry[entry].finished = 1; wmb(); mce->finished = 1; set_bit(0, &mce_need_notify); }