Merge branch 'fixes' of http://ftp.arm.linux.org.uk/pub/linux/arm/kernel/git-cur...
[pandora-kernel.git] / arch / powerpc / sysdev / mpic.c
index d5d3ff3..8c7e852 100644 (file)
@@ -800,8 +800,6 @@ static void mpic_end_ipi(struct irq_data *d)
         * IPIs are marked IRQ_PER_CPU. This has the side effect of
         * preventing the IRQ_PENDING/IRQ_INPROGRESS logic from
         * applying to them. We EOI them late to avoid re-entering.
-        * We mark IPI's with IRQF_DISABLED as they must run with
-        * irqs disabled.
         */
        mpic_eoi(mpic);
 }
@@ -1285,13 +1283,11 @@ struct mpic * __init mpic_alloc(struct device_node *node,
                           mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
                           | MPIC_GREG_GCONF_MCK);
 
-       /* Read feature register, calculate num CPUs and, for non-ISU
-        * MPICs, num sources as well. On ISU MPICs, sources are counted
-        * as ISUs are added
+       /*
+        * Read feature register.  For non-ISU MPICs, num sources as well. On
+        * ISU MPICs, sources are counted as ISUs are added
         */
        greg_feature = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0));
-       mpic->num_cpus = ((greg_feature & MPIC_GREG_FEATURE_LAST_CPU_MASK)
-                         >> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1;
        if (isu_size == 0) {
                if (flags & MPIC_BROKEN_FRR_NIRQS)
                        mpic->num_sources = mpic->irq_count;
@@ -1301,10 +1297,18 @@ struct mpic * __init mpic_alloc(struct device_node *node,
                                 >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1;
        }
 
+       /*
+        * The MPIC driver will crash if there are more cores than we
+        * can initialize, so we may as well catch that problem here.
+        */
+       BUG_ON(num_possible_cpus() > MPIC_MAX_CPUS);
+
        /* Map the per-CPU registers */
-       for (i = 0; i < mpic->num_cpus; i++) {
-               mpic_map(mpic, node, paddr, &mpic->cpuregs[i],
-                        MPIC_INFO(CPU_BASE) + i * MPIC_INFO(CPU_STRIDE),
+       for_each_possible_cpu(i) {
+               unsigned int cpu = get_hard_smp_processor_id(i);
+
+               mpic_map(mpic, node, paddr, &mpic->cpuregs[cpu],
+                        MPIC_INFO(CPU_BASE) + cpu * MPIC_INFO(CPU_STRIDE),
                         0x1000);
        }
 
@@ -1343,7 +1347,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
        }
        printk(KERN_INFO "mpic: Setting up MPIC \"%s\" version %s at %llx,"
               " max %d CPUs\n",
-              name, vers, (unsigned long long)paddr, mpic->num_cpus);
+              name, vers, (unsigned long long)paddr, num_possible_cpus());
        printk(KERN_INFO "mpic: ISU size: %d, shift: %d, mask: %x\n",
               mpic->isu_size, mpic->isu_shift, mpic->isu_mask);
 
@@ -1742,6 +1746,7 @@ void mpic_reset_core(int cpu)
        struct mpic *mpic = mpic_primary;
        u32 pir;
        int cpuid = get_hard_smp_processor_id(cpu);
+       int i;
 
        /* Set target bit for core reset */
        pir = mpic_read(mpic->gregs, MPIC_INFO(GREG_PROCESSOR_INIT));
@@ -1753,6 +1758,15 @@ void mpic_reset_core(int cpu)
        pir &= ~(1 << cpuid);
        mpic_write(mpic->gregs, MPIC_INFO(GREG_PROCESSOR_INIT), pir);
        mpic_read(mpic->gregs, MPIC_INFO(GREG_PROCESSOR_INIT));
+
+       /* Perform 15 EOI on each reset core to clear pending interrupts.
+        * This is required for FSL CoreNet based devices */
+       if (mpic->flags & MPIC_FSL) {
+               for (i = 0; i < 15; i++) {
+                       _mpic_write(mpic->reg_type, &mpic->cpuregs[cpuid],
+                                     MPIC_CPU_EOI, 0);
+               }
+       }
 }
 #endif /* CONFIG_SMP */