Commit a84195f3 authored by Arnd Bergmann's avatar Arnd Bergmann Committed by Paul Mackerras

[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: default avatarArnd Bergmann <arndb@de.ibm.com>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent 5f502413
...@@ -205,6 +205,18 @@ static struct iic_regs __iomem *find_iic(int cpu) ...@@ -205,6 +205,18 @@ static struct iic_regs __iomem *find_iic(int cpu)
} }
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
/* Use the highest interrupt priorities for IPI */
static inline int iic_ipi_to_irq(int ipi)
{
return IIC_IPI_OFFSET + IIC_NUM_IPIS - 1 - ipi;
}
static inline int iic_irq_to_ipi(int irq)
{
return IIC_NUM_IPIS - 1 - (irq - IIC_IPI_OFFSET);
}
void iic_setup_cpu(void) void iic_setup_cpu(void)
{ {
out_be64(&__get_cpu_var(iic).regs->prio, 0xff); out_be64(&__get_cpu_var(iic).regs->prio, 0xff);
...@@ -212,18 +224,20 @@ void iic_setup_cpu(void) ...@@ -212,18 +224,20 @@ void iic_setup_cpu(void)
void iic_cause_IPI(int cpu, int mesg) void iic_cause_IPI(int cpu, int mesg)
{ {
out_be64(&per_cpu(iic, cpu).regs->generate, mesg); out_be64(&per_cpu(iic, cpu).regs->generate, (IIC_NUM_IPIS - 1 - mesg) << 4);
} }
static irqreturn_t iic_ipi_action(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t iic_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
{ {
smp_message_recv(iic_irq_to_ipi(irq), regs);
smp_message_recv(irq - IIC_IPI_OFFSET, regs);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static void iic_request_ipi(int irq, const char *name) static void iic_request_ipi(int ipi, const char *name)
{ {
int irq;
irq = iic_ipi_to_irq(ipi);
/* IPIs are marked SA_INTERRUPT as they must run with irqs /* IPIs are marked SA_INTERRUPT as they must run with irqs
* disabled */ * disabled */
get_irq_desc(irq)->handler = &iic_pic; get_irq_desc(irq)->handler = &iic_pic;
...@@ -233,10 +247,10 @@ static void iic_request_ipi(int irq, const char *name) ...@@ -233,10 +247,10 @@ static void iic_request_ipi(int irq, const char *name)
void iic_request_IPIs(void) void iic_request_IPIs(void)
{ {
iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_CALL_FUNCTION, "IPI-call"); iic_request_ipi(PPC_MSG_CALL_FUNCTION, "IPI-call");
iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_RESCHEDULE, "IPI-resched"); iic_request_ipi(PPC_MSG_RESCHEDULE, "IPI-resched");
#ifdef CONFIG_DEBUGGER #ifdef CONFIG_DEBUGGER
iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_DEBUGGER_BREAK, "IPI-debug"); iic_request_ipi(PPC_MSG_DEBUGGER_BREAK, "IPI-debug");
#endif /* CONFIG_DEBUGGER */ #endif /* CONFIG_DEBUGGER */
} }
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment