diff options
author | Arnd Bergmann <arnd@arndb.de> | 2005-08-18 13:35:21 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2005-09-09 08:11:34 -0400 |
commit | a84195f36e373001e6eed2e95a5dc1994cf30480 (patch) | |
tree | eafa49d8a9e6f4d725a498626029b7abf3ff9d91 /arch/ppc64 | |
parent | 5f5024130287a9467a41b9f94ec170958ae45cbd (diff) |
[PATCH] ppc64: fix IPI on bpa_iic
This fixes a severe bug in the bpa_iic driver that caused
all sorts of problems.
We had been using incorrect priority values for inter processor
interrupts, which resulted in always doing CALL_FUNCTION
instead of RESCHEDULE or DEBUGGER_BREAK.
The symptoms cured by this patch include bad performance on
SMP systems spurious kernel panics in the IPI code.
Signed-off-by: Arnd Bergmann <arndb@de.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/ppc64')
-rw-r--r-- | arch/ppc64/kernel/bpa_iic.c | 28 |
1 files changed, 21 insertions, 7 deletions
diff --git a/arch/ppc64/kernel/bpa_iic.c b/arch/ppc64/kernel/bpa_iic.c index c8f3dc3fad70..0aaa878e19d3 100644 --- a/arch/ppc64/kernel/bpa_iic.c +++ b/arch/ppc64/kernel/bpa_iic.c | |||
@@ -205,6 +205,18 @@ static struct iic_regs __iomem *find_iic(int cpu) | |||
205 | } | 205 | } |
206 | 206 | ||
207 | #ifdef CONFIG_SMP | 207 | #ifdef CONFIG_SMP |
208 | |||
209 | /* Use the highest interrupt priorities for IPI */ | ||
210 | static inline int iic_ipi_to_irq(int ipi) | ||
211 | { | ||
212 | return IIC_IPI_OFFSET + IIC_NUM_IPIS - 1 - ipi; | ||
213 | } | ||
214 | |||
215 | static inline int iic_irq_to_ipi(int irq) | ||
216 | { | ||
217 | return IIC_NUM_IPIS - 1 - (irq - IIC_IPI_OFFSET); | ||
218 | } | ||
219 | |||
208 | void iic_setup_cpu(void) | 220 | void iic_setup_cpu(void) |
209 | { | 221 | { |
210 | out_be64(&__get_cpu_var(iic).regs->prio, 0xff); | 222 | out_be64(&__get_cpu_var(iic).regs->prio, 0xff); |
@@ -212,18 +224,20 @@ void iic_setup_cpu(void) | |||
212 | 224 | ||
213 | void iic_cause_IPI(int cpu, int mesg) | 225 | void iic_cause_IPI(int cpu, int mesg) |
214 | { | 226 | { |
215 | out_be64(&per_cpu(iic, cpu).regs->generate, mesg); | 227 | out_be64(&per_cpu(iic, cpu).regs->generate, (IIC_NUM_IPIS - 1 - mesg) << 4); |
216 | } | 228 | } |
217 | 229 | ||
218 | static irqreturn_t iic_ipi_action(int irq, void *dev_id, struct pt_regs *regs) | 230 | static irqreturn_t iic_ipi_action(int irq, void *dev_id, struct pt_regs *regs) |
219 | { | 231 | { |
220 | 232 | smp_message_recv(iic_irq_to_ipi(irq), regs); | |
221 | smp_message_recv(irq - IIC_IPI_OFFSET, regs); | ||
222 | return IRQ_HANDLED; | 233 | return IRQ_HANDLED; |
223 | } | 234 | } |
224 | 235 | ||
225 | static void iic_request_ipi(int irq, const char *name) | 236 | static void iic_request_ipi(int ipi, const char *name) |
226 | { | 237 | { |
238 | int irq; | ||
239 | |||
240 | irq = iic_ipi_to_irq(ipi); | ||
227 | /* IPIs are marked SA_INTERRUPT as they must run with irqs | 241 | /* IPIs are marked SA_INTERRUPT as they must run with irqs |
228 | * disabled */ | 242 | * disabled */ |
229 | get_irq_desc(irq)->handler = &iic_pic; | 243 | get_irq_desc(irq)->handler = &iic_pic; |
@@ -233,10 +247,10 @@ static void iic_request_ipi(int irq, const char *name) | |||
233 | 247 | ||
234 | void iic_request_IPIs(void) | 248 | void iic_request_IPIs(void) |
235 | { | 249 | { |
236 | iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_CALL_FUNCTION, "IPI-call"); | 250 | iic_request_ipi(PPC_MSG_CALL_FUNCTION, "IPI-call"); |
237 | iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_RESCHEDULE, "IPI-resched"); | 251 | iic_request_ipi(PPC_MSG_RESCHEDULE, "IPI-resched"); |
238 | #ifdef CONFIG_DEBUGGER | 252 | #ifdef CONFIG_DEBUGGER |
239 | iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_DEBUGGER_BREAK, "IPI-debug"); | 253 | iic_request_ipi(PPC_MSG_DEBUGGER_BREAK, "IPI-debug"); |
240 | #endif /* CONFIG_DEBUGGER */ | 254 | #endif /* CONFIG_DEBUGGER */ |
241 | } | 255 | } |
242 | #endif /* CONFIG_SMP */ | 256 | #endif /* CONFIG_SMP */ |