summaryrefslogtreecommitdiff
path: root/arch/powerpc/sysdev/mpic.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/sysdev/mpic.c')
-rw-r--r--arch/powerpc/sysdev/mpic.c36
1 files changed, 25 insertions, 11 deletions
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index d5d3ff3d757e..8c7e8528e7c4 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -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 */