diff options
author | Michael Ellerman <michael@ellerman.id.au> | 2009-07-05 12:08:52 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2009-08-19 20:12:22 -0400 |
commit | 11a6b292c1bc9cb39970e44edd6958250f23d3a8 (patch) | |
tree | ac23c82f0739ad7521b531f570305d2a306c7651 /arch/powerpc/sysdev | |
parent | 66dc3304f3875ea85c630a57a88ecf79032890c4 (diff) |
powerpc/mpic: Fix MPIC_BROKEN_REGREAD on non broken MPICs
The workaround enabled by CONFIG_MPIC_BROKEN_REGREAD does not work
on non-broken MPICs. The symptom is no interrupts being received.
The fix is twofold. Firstly the code was broken for multiple isus,
we need to index into the shadow array with the src_no, not the idx.
Secondly, we always do the read, but only use the VECPRI_MASK and
VECPRI_ACTIVITY bits from the hardware, the rest of "val" comes
from the shadow.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Olof Johansson <olof@lixom.net>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/sysdev')
-rw-r--r-- | arch/powerpc/sysdev/mpic.c | 13 |
1 files changed, 8 insertions, 5 deletions
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 3981ae4cb58e..30c44e6b0413 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c | |||
@@ -230,14 +230,16 @@ static inline u32 _mpic_irq_read(struct mpic *mpic, unsigned int src_no, unsigne | |||
230 | { | 230 | { |
231 | unsigned int isu = src_no >> mpic->isu_shift; | 231 | unsigned int isu = src_no >> mpic->isu_shift; |
232 | unsigned int idx = src_no & mpic->isu_mask; | 232 | unsigned int idx = src_no & mpic->isu_mask; |
233 | unsigned int val; | ||
233 | 234 | ||
235 | val = _mpic_read(mpic->reg_type, &mpic->isus[isu], | ||
236 | reg + (idx * MPIC_INFO(IRQ_STRIDE))); | ||
234 | #ifdef CONFIG_MPIC_BROKEN_REGREAD | 237 | #ifdef CONFIG_MPIC_BROKEN_REGREAD |
235 | if (reg == 0) | 238 | if (reg == 0) |
236 | return mpic->isu_reg0_shadow[idx]; | 239 | val = (val & (MPIC_VECPRI_MASK | MPIC_VECPRI_ACTIVITY)) | |
237 | else | 240 | mpic->isu_reg0_shadow[src_no]; |
238 | #endif | 241 | #endif |
239 | return _mpic_read(mpic->reg_type, &mpic->isus[isu], | 242 | return val; |
240 | reg + (idx * MPIC_INFO(IRQ_STRIDE))); | ||
241 | } | 243 | } |
242 | 244 | ||
243 | static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no, | 245 | static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no, |
@@ -251,7 +253,8 @@ static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no, | |||
251 | 253 | ||
252 | #ifdef CONFIG_MPIC_BROKEN_REGREAD | 254 | #ifdef CONFIG_MPIC_BROKEN_REGREAD |
253 | if (reg == 0) | 255 | if (reg == 0) |
254 | mpic->isu_reg0_shadow[idx] = value; | 256 | mpic->isu_reg0_shadow[src_no] = |
257 | value & ~(MPIC_VECPRI_MASK | MPIC_VECPRI_ACTIVITY); | ||
255 | #endif | 258 | #endif |
256 | } | 259 | } |
257 | 260 | ||