From: Zwane Mwaikambo <zwane@arm.linux.org.uk>

Ensure that we only offline the processor when it's safe and never run
softirqs in another processor's ksoftirqd context.  This also gets rid of
the warnings in ksoftirqd on cpu offline.

Signed-off-by: Zwane Mwaikambo <zwane@arm.linux.org.uk>
Acked-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/kernel/softirq.c |   12 ++++++++----
 1 files changed, 8 insertions(+), 4 deletions(-)

diff -puN kernel/softirq.c~run-softirqs-on-proper-processor-on-offline kernel/softirq.c
--- 25/kernel/softirq.c~run-softirqs-on-proper-processor-on-offline	2005-02-15 21:42:54.000000000 -0800
+++ 25-akpm/kernel/softirq.c	2005-02-15 21:42:54.000000000 -0800
@@ -355,8 +355,12 @@ static int ksoftirqd(void * __bind_cpu)
 	set_current_state(TASK_INTERRUPTIBLE);
 
 	while (!kthread_should_stop()) {
-		if (!local_softirq_pending())
+		preempt_disable();
+		if (!local_softirq_pending()) {
+			preempt_enable_no_resched();
 			schedule();
+			preempt_disable();
+		}
 
 		__set_current_state(TASK_RUNNING);
 
@@ -364,14 +368,14 @@ static int ksoftirqd(void * __bind_cpu)
 			/* Preempt disable stops cpu going offline.
 			   If already offline, we'll be on wrong CPU:
 			   don't process */
-			preempt_disable();
 			if (cpu_is_offline((long)__bind_cpu))
 				goto wait_to_die;
 			do_softirq();
-			preempt_enable();
+			preempt_enable_no_resched();
 			cond_resched();
+			preempt_disable();
 		}
-
+		preempt_enable();
 		set_current_state(TASK_INTERRUPTIBLE);
 	}
 	__set_current_state(TASK_RUNNING);
_