From: Rusty Russell <rusty@rustcorp.com.au>

Andi Kleen reported a problem where a very slow boot caused the timer
interrupt on a secondary CPU to go off before the CPU was actually brought
up by the core code, so the CPU_PREPARE notifier hadn't been called, so the
per-cpu timer code wasn't set up.

This was caused by enabling interrupts around calibrate_delay() on
secondary CPUs, which is not actually neccessary (interrupts on CPU 0
increments jiffies, which is all that is required).  So delay enabling
interrupts until the actual __cpu_up() call for that CPU.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/arch/i386/kernel/apic.c    |    2 --
 25-akpm/arch/i386/kernel/smpboot.c |    8 +++++---
 2 files changed, 5 insertions(+), 5 deletions(-)

diff -puN arch/i386/kernel/apic.c~x86-no-interrupts-from-secondary-cpus-until-officially-online arch/i386/kernel/apic.c
--- 25/arch/i386/kernel/apic.c~x86-no-interrupts-from-secondary-cpus-until-officially-online	2005-01-16 23:22:01.400045728 -0800
+++ 25-akpm/arch/i386/kernel/apic.c	2005-01-16 23:22:01.407044664 -0800
@@ -1046,9 +1046,7 @@ void __init setup_boot_APIC_clock(void)
 
 void __init setup_secondary_APIC_clock(void)
 {
-	local_irq_disable(); /* FIXME: Do we need this? --RR */
 	setup_APIC_timer(calibration_result);
-	local_irq_enable();
 }
 
 void __init disable_APIC_timer(void)
diff -puN arch/i386/kernel/smpboot.c~x86-no-interrupts-from-secondary-cpus-until-officially-online arch/i386/kernel/smpboot.c
--- 25/arch/i386/kernel/smpboot.c~x86-no-interrupts-from-secondary-cpus-until-officially-online	2005-01-16 23:22:01.401045576 -0800
+++ 25-akpm/arch/i386/kernel/smpboot.c	2005-01-16 23:22:01.406044816 -0800
@@ -384,8 +384,6 @@ void __init smp_callin(void)
 	setup_local_APIC();
 	map_cpu_to_logical_apicid();
 
-	local_irq_enable();
-
 	/*
 	 * Get our bogomips.
 	 */
@@ -398,7 +396,7 @@ void __init smp_callin(void)
  	smp_store_cpu_info(cpuid);
 
 	disable_APIC_timer();
-	local_irq_disable();
+
 	/*
 	 * Allow the master to continue.
 	 */
@@ -440,6 +438,10 @@ static void __init start_secondary(void 
 	 */
 	local_flush_tlb();
 	cpu_set(smp_processor_id(), cpu_online_map);
+
+	/* We can take interrupts now: we're officially "up". */
+	local_irq_enable();
+
 	wmb();
 	cpu_idle();
 }
_