Andi notes that the

	smp_call_function(foo);
	foo();

in there is incorrect on preemptible kernels.

Fix that by using on_each_cpu(), which takes care of such things.

Also, remove the open-coded timer from here.  We have
schedule_delayed_work().

And remove the `timerset' variable, which doesn't do anything.



---

 arch/i386/kernel/cpu/mcheck/non-fatal.c |   41 ++++++++------------------------
 1 files changed, 11 insertions(+), 30 deletions(-)

diff -puN arch/i386/kernel/cpu/mcheck/non-fatal.c~mce-preempt-fixes arch/i386/kernel/cpu/mcheck/non-fatal.c
--- 25/arch/i386/kernel/cpu/mcheck/non-fatal.c~mce-preempt-fixes	2004-02-06 20:39:30.000000000 -0800
+++ 25-akpm/arch/i386/kernel/cpu/mcheck/non-fatal.c	2004-02-06 20:47:54.000000000 -0800
@@ -24,8 +24,6 @@
 
 #include "mce.h"
 
-static struct timer_list mce_timer;
-static int timerset;
 static int firstbank;
 
 #define MCE_RATE	15*HZ	/* timer rate is 15s */
@@ -35,7 +33,6 @@ static void mce_checkregs (void *info)
 	u32 low, high;
 	int i;
 
-	preempt_disable(); 
 	for (i=firstbank; i<nr_mce_banks; i++) {
 		rdmsr (MSR_IA32_MC0_STATUS+i*4, low, high);
 
@@ -53,27 +50,17 @@ static void mce_checkregs (void *info)
 			wmb();
 		}
 	}
-	preempt_enable();
 }
 
-static void do_mce_timer(void *data)
+static void mce_work_fn(void *data);
+static DECLARE_WORK(mce_work, mce_work_fn, NULL);
+
+static void mce_work_fn(void *data)
 { 
-	smp_call_function (mce_checkregs, NULL, 1, 1);
+	on_each_cpu(mce_checkregs, NULL, 1, 1);
+	schedule_delayed_work(&mce_work, MCE_RATE);
 } 
 
-static DECLARE_WORK(mce_work, do_mce_timer, NULL);
-
-static void mce_timerfunc (unsigned long data)
-{
-	mce_checkregs (NULL);
-#ifdef CONFIG_SMP
-	if (num_online_cpus() > 1) 
-		schedule_work (&mce_work); 
-#endif
-	mce_timer.expires = jiffies + MCE_RATE;
-	add_timer (&mce_timer);
-}	
-
 static int __init init_nonfatal_mce_checker(void)
 {
 	struct cpuinfo_x86 *c = &boot_cpu_data;
@@ -93,17 +80,11 @@ static int __init init_nonfatal_mce_chec
 	else
 			firstbank = 0;
 
-	if (timerset == 0) {
-		/* Set the timer to check for non-fatal
-		   errors every MCE_RATE seconds */
-		init_timer (&mce_timer);
-		mce_timer.expires = jiffies + MCE_RATE;
-		mce_timer.data = 0;
-		mce_timer.function = &mce_timerfunc;
-		add_timer (&mce_timer);
-		timerset = 1;
-		printk(KERN_INFO "Machine check exception polling timer started.\n");
-	}
+	/*
+	 * Check for non-fatal errors every MCE_RATE s
+	 */
+	schedule_delayed_work(&mce_work, MCE_RATE);
+	printk(KERN_INFO "Machine check exception polling timer started.\n");
 	return 0;
 }
 module_init(init_nonfatal_mce_checker);

_