Merge remote-tracking branch 'stable/linux-3.0.y' into android-3.0
[firefly-linux-kernel-4.4.55.git] / arch / arm / kernel / smp.c
index 9739bb8a2d2863bc09c715c1b9ce6316a7780540..e895f97ab008844fb97192f67b33d4ea692b03ea 100644 (file)
@@ -278,20 +278,26 @@ static void __cpuinit smp_store_cpu_info(unsigned int cpuid)
 asmlinkage void __cpuinit secondary_start_kernel(void)
 {
        struct mm_struct *mm = &init_mm;
-       unsigned int cpu = smp_processor_id();
+       unsigned int cpu;
 
-       printk("CPU%u: Booted secondary processor\n", cpu);
+       /*
+        * The identity mapping is uncached (strongly ordered), so
+        * switch away from it before attempting any exclusive accesses.
+        */
+       cpu_switch_mm(mm->pgd, mm);
+       enter_lazy_tlb(mm, current);
+       local_flush_tlb_all();
 
        /*
         * All kernel threads share the same mm context; grab a
         * reference and switch to it.
         */
+       cpu = smp_processor_id();
        atomic_inc(&mm->mm_count);
        current->active_mm = mm;
        cpumask_set_cpu(cpu, mm_cpumask(mm));
-       cpu_switch_mm(mm->pgd, mm);
-       enter_lazy_tlb(mm, current);
-       local_flush_tlb_all();
+
+       printk("CPU%u: Booted secondary processor\n", cpu);
 
        cpu_init();
        preempt_disable();
@@ -450,9 +456,7 @@ static DEFINE_PER_CPU(struct clock_event_device, percpu_clockevent);
 static void ipi_timer(void)
 {
        struct clock_event_device *evt = &__get_cpu_var(percpu_clockevent);
-       irq_enter();
        evt->event_handler(evt);
-       irq_exit();
 }
 
 #ifdef CONFIG_LOCAL_TIMERS
@@ -463,7 +467,9 @@ asmlinkage void __exception_irq_entry do_local_timer(struct pt_regs *regs)
 
        if (local_timer_ack()) {
                __inc_irq_stat(cpu, local_timer_irqs);
+               irq_enter();
                ipi_timer();
+               irq_exit();
        }
 
        set_irq_regs(old_regs);
@@ -625,7 +631,9 @@ asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs)
 
        switch (ipinr) {
        case IPI_TIMER:
+               irq_enter();
                ipi_timer();
+               irq_exit();
                break;
 
        case IPI_RESCHEDULE:
@@ -633,15 +641,21 @@ asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs)
                break;
 
        case IPI_CALL_FUNC:
+               irq_enter();
                generic_smp_call_function_interrupt();
+               irq_exit();
                break;
 
        case IPI_CALL_FUNC_SINGLE:
+               irq_enter();
                generic_smp_call_function_single_interrupt();
+               irq_exit();
                break;
 
        case IPI_CPU_STOP:
+               irq_enter();
                ipi_cpu_stop(cpu);
+               irq_exit();
                break;
 
        case IPI_CPU_BACKTRACE: