diff options
author | Andi Kleen <andi@firstfloor.org> | 2009-02-12 07:39:28 -0500 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2009-02-17 18:32:41 -0500 |
commit | 9bd984058088d6ef7af6946591a207e51a2f4890 (patch) | |
tree | 538a5ae886a21f3086918e3738813ff55a9818bc /arch/x86/kernel/cpu | |
parent | 123aa76ec0cab5d4881cd8509faed43231e68801 (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.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 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 | ||
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; |