diff options
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce_64.c | 25 |
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 | ||
383 | static void mce_do_trigger(struct work_struct *work) | ||
384 | { | ||
385 | call_usermodehelper(trigger, trigger_argv, NULL, UMH_NO_WAIT); | ||
386 | } | ||
387 | |||
388 | static 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 | */ |
389 | int mce_notify_user(void) | 395 | int 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; |