diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2009-06-22 12:47:59 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2009-06-26 00:37:22 -0400 |
commit | 5a2642f620eb6e40792822fa0eafe23046fbb55e (patch) | |
tree | 639c2697e07ca65c970837281239bcbb41f202e5 /arch | |
parent | 6f0b1c6094b3e8eeeb13f8f16c1b2ef452a6f519 (diff) |
powerpc/mpic: Fix mapping of "DCR" based MPIC variants
Commit 31207dab7d2e63795eb15823947bd2f7025b08e2
"Fix incorrect allocation of interrupt rev-map"
introduced a regression crashing on boot on machines using
a "DCR" based MPIC, such as the Cell blades.
The reason is that the irq host data structure is initialized
much later as a result of that patch, causing our calls to
mpic_map() do be done before we have a host setup.
Unfortunately, this breaks _mpic_map_dcr() which uses the
mpic->irqhost to get to the device node.
This fixes it by, instead, passing the device node explicitely
to mpic_map().
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Akira Tsukamoto <akirat@rd.scei.sony.co.jp>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/sysdev/mpic.c | 29 |
1 files changed, 16 insertions, 13 deletions
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 9c3af5045495..32a2e950f563 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c | |||
@@ -279,28 +279,29 @@ static void _mpic_map_mmio(struct mpic *mpic, phys_addr_t phys_addr, | |||
279 | } | 279 | } |
280 | 280 | ||
281 | #ifdef CONFIG_PPC_DCR | 281 | #ifdef CONFIG_PPC_DCR |
282 | static void _mpic_map_dcr(struct mpic *mpic, struct mpic_reg_bank *rb, | 282 | static void _mpic_map_dcr(struct mpic *mpic, struct device_node *node, |
283 | struct mpic_reg_bank *rb, | ||
283 | unsigned int offset, unsigned int size) | 284 | unsigned int offset, unsigned int size) |
284 | { | 285 | { |
285 | const u32 *dbasep; | 286 | const u32 *dbasep; |
286 | 287 | ||
287 | dbasep = of_get_property(mpic->irqhost->of_node, "dcr-reg", NULL); | 288 | dbasep = of_get_property(node, "dcr-reg", NULL); |
288 | 289 | ||
289 | rb->dhost = dcr_map(mpic->irqhost->of_node, *dbasep + offset, size); | 290 | rb->dhost = dcr_map(node, *dbasep + offset, size); |
290 | BUG_ON(!DCR_MAP_OK(rb->dhost)); | 291 | BUG_ON(!DCR_MAP_OK(rb->dhost)); |
291 | } | 292 | } |
292 | 293 | ||
293 | static inline void mpic_map(struct mpic *mpic, phys_addr_t phys_addr, | 294 | static inline void mpic_map(struct mpic *mpic, struct device_node *node, |
294 | struct mpic_reg_bank *rb, unsigned int offset, | 295 | phys_addr_t phys_addr, struct mpic_reg_bank *rb, |
295 | unsigned int size) | 296 | unsigned int offset, unsigned int size) |
296 | { | 297 | { |
297 | if (mpic->flags & MPIC_USES_DCR) | 298 | if (mpic->flags & MPIC_USES_DCR) |
298 | _mpic_map_dcr(mpic, rb, offset, size); | 299 | _mpic_map_dcr(mpic, node, rb, offset, size); |
299 | else | 300 | else |
300 | _mpic_map_mmio(mpic, phys_addr, rb, offset, size); | 301 | _mpic_map_mmio(mpic, phys_addr, rb, offset, size); |
301 | } | 302 | } |
302 | #else /* CONFIG_PPC_DCR */ | 303 | #else /* CONFIG_PPC_DCR */ |
303 | #define mpic_map(m,p,b,o,s) _mpic_map_mmio(m,p,b,o,s) | 304 | #define mpic_map(m,n,p,b,o,s) _mpic_map_mmio(m,p,b,o,s) |
304 | #endif /* !CONFIG_PPC_DCR */ | 305 | #endif /* !CONFIG_PPC_DCR */ |
305 | 306 | ||
306 | 307 | ||
@@ -1152,8 +1153,8 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
1152 | } | 1153 | } |
1153 | 1154 | ||
1154 | /* Map the global registers */ | 1155 | /* Map the global registers */ |
1155 | mpic_map(mpic, paddr, &mpic->gregs, MPIC_INFO(GREG_BASE), 0x1000); | 1156 | mpic_map(mpic, node, paddr, &mpic->gregs, MPIC_INFO(GREG_BASE), 0x1000); |
1156 | mpic_map(mpic, paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000); | 1157 | mpic_map(mpic, node, paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000); |
1157 | 1158 | ||
1158 | /* Reset */ | 1159 | /* Reset */ |
1159 | if (flags & MPIC_WANTS_RESET) { | 1160 | if (flags & MPIC_WANTS_RESET) { |
@@ -1194,7 +1195,7 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
1194 | 1195 | ||
1195 | /* Map the per-CPU registers */ | 1196 | /* Map the per-CPU registers */ |
1196 | for (i = 0; i < mpic->num_cpus; i++) { | 1197 | for (i = 0; i < mpic->num_cpus; i++) { |
1197 | mpic_map(mpic, paddr, &mpic->cpuregs[i], | 1198 | mpic_map(mpic, node, paddr, &mpic->cpuregs[i], |
1198 | MPIC_INFO(CPU_BASE) + i * MPIC_INFO(CPU_STRIDE), | 1199 | MPIC_INFO(CPU_BASE) + i * MPIC_INFO(CPU_STRIDE), |
1199 | 0x1000); | 1200 | 0x1000); |
1200 | } | 1201 | } |
@@ -1202,7 +1203,7 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
1202 | /* Initialize main ISU if none provided */ | 1203 | /* Initialize main ISU if none provided */ |
1203 | if (mpic->isu_size == 0) { | 1204 | if (mpic->isu_size == 0) { |
1204 | mpic->isu_size = mpic->num_sources; | 1205 | mpic->isu_size = mpic->num_sources; |
1205 | mpic_map(mpic, paddr, &mpic->isus[0], | 1206 | mpic_map(mpic, node, paddr, &mpic->isus[0], |
1206 | MPIC_INFO(IRQ_BASE), MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); | 1207 | MPIC_INFO(IRQ_BASE), MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); |
1207 | } | 1208 | } |
1208 | mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1); | 1209 | mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1); |
@@ -1256,8 +1257,10 @@ void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num, | |||
1256 | 1257 | ||
1257 | BUG_ON(isu_num >= MPIC_MAX_ISU); | 1258 | BUG_ON(isu_num >= MPIC_MAX_ISU); |
1258 | 1259 | ||
1259 | mpic_map(mpic, paddr, &mpic->isus[isu_num], 0, | 1260 | mpic_map(mpic, mpic->irqhost->of_node, |
1261 | paddr, &mpic->isus[isu_num], 0, | ||
1260 | MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); | 1262 | MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); |
1263 | |||
1261 | if ((isu_first + mpic->isu_size) > mpic->num_sources) | 1264 | if ((isu_first + mpic->isu_size) > mpic->num_sources) |
1262 | mpic->num_sources = isu_first + mpic->isu_size; | 1265 | mpic->num_sources = isu_first + mpic->isu_size; |
1263 | } | 1266 | } |