aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 25ccdbec86e2..18b379cf0610 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;