aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/cpu
diff options
context:
space:
mode:
authorAndi Kleen <andi@firstfloor.org>2009-02-12 07:39:28 -0500
committerH. Peter Anvin <hpa@linux.intel.com>2009-02-17 18:32:41 -0500
commit9bd984058088d6ef7af6946591a207e51a2f4890 (patch)
tree538a5ae886a21f3086918e3738813ff55a9818bc /arch/x86/kernel/cpu
parent123aa76ec0cab5d4881cd8509faed43231e68801 (diff)
x86, mce: always use separate work queue to run trigger
Impact: Needed for bug fix in next patch This relaxes the requirement that mce_notify_user has to run in process context. Useful for future changes, but also leads to cleaner behaviour now. Now instead mce_notify_user can be called directly from interrupt (but not NMI) context. The work queue only uses a single global work struct, which can be done safely because it is always free to reuse before the trigger function is executed. This way no events can be lost. Signed-off-by: Andi Kleen <ak@linux.intel.com> Acked-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'arch/x86/kernel/cpu')
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_64.c25
1 files changed, 18 insertions, 7 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/mce_64.c b/arch/x86/kernel/cpu/mcheck/mce_64.c
index 25ccdbec86e..18b379cf061 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_64.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_64.c
@@ -380,11 +380,17 @@ static void mcheck_timer(struct work_struct *work)
380 schedule_delayed_work(&mcheck_work, next_interval); 380 schedule_delayed_work(&mcheck_work, next_interval);
381} 381}
382 382
383static void mce_do_trigger(struct work_struct *work)
384{
385 call_usermodehelper(trigger, trigger_argv, NULL, UMH_NO_WAIT);
386}
387
388static DECLARE_WORK(mce_trigger_work, mce_do_trigger);
389
383/* 390/*
384 * This is only called from process context. This is where we do 391 * Notify the user(s) about new machine check events.
385 * anything we need to alert userspace about new MCEs. This is called 392 * Can be called from interrupt context, but not from machine check/NMI
386 * directly from the poller and also from entry.S and idle, thanks to 393 * context.
387 * TIF_MCE_NOTIFY.
388 */ 394 */
389int mce_notify_user(void) 395int mce_notify_user(void)
390{ 396{
@@ -394,9 +400,14 @@ int mce_notify_user(void)
394 unsigned long now = jiffies; 400 unsigned long now = jiffies;
395 401
396 wake_up_interruptible(&mce_wait); 402 wake_up_interruptible(&mce_wait);
397 if (trigger[0]) 403
398 call_usermodehelper(trigger, trigger_argv, NULL, 404 /*
399 UMH_NO_WAIT); 405 * There is no risk of missing notifications because
406 * work_pending is always cleared before the function is
407 * executed.
408 */
409 if (trigger[0] && !work_pending(&mce_trigger_work))
410 schedule_work(&mce_trigger_work);
400 411
401 if (time_after_eq(now, last_print + (check_interval*HZ))) { 412 if (time_after_eq(now, last_print + (check_interval*HZ))) {
402 last_print = now; 413 last_print = now;