From: Arnd Bergmann Date: Thu, 18 Aug 2005 17:35:21 +0000 (+0200) Subject: [PATCH] ppc64: fix IPI on bpa_iic X-Git-Tag: v2.6.14-rc1~482^2~13 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a84195f36e373001e6eed2e95a5dc1994cf30480;p=linux-2.6 [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 Signed-off-by: Paul Mackerras --- diff --git a/arch/ppc64/kernel/bpa_iic.c b/arch/ppc64/kernel/bpa_iic.c index c8f3dc3fad..0aaa878e19 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) } #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) { out_be64(&__get_cpu_var(iic).regs->prio, 0xff); @@ -212,18 +224,20 @@ void iic_setup_cpu(void) 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) { - - smp_message_recv(irq - IIC_IPI_OFFSET, regs); + smp_message_recv(iic_irq_to_ipi(irq), regs); 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 * disabled */ get_irq_desc(irq)->handler = &iic_pic; @@ -233,10 +247,10 @@ static void iic_request_ipi(int irq, const char *name) void iic_request_IPIs(void) { - iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_CALL_FUNCTION, "IPI-call"); - iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_RESCHEDULE, "IPI-resched"); + iic_request_ipi(PPC_MSG_CALL_FUNCTION, "IPI-call"); + iic_request_ipi(PPC_MSG_RESCHEDULE, "IPI-resched"); #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_SMP */