| From 30539e4c7e406d75c8c2fa520c58e00779079acb Mon Sep 17 00:00:00 2001 |
| From: Felix Fietkau <nbd@nbd.name> |
| Date: Thu, 19 Jan 2017 12:28:22 +0100 |
| Subject: [PATCH] MIPS: Lantiq: Fix cascaded IRQ setup |
| |
| commit 6c356eda225e3ee134ed4176b9ae3a76f793f4dd upstream. |
| |
| With the IRQ stack changes integrated, the XRX200 devices started |
| emitting a constant stream of kernel messages like this: |
| |
| [ 565.415310] Spurious IRQ: CAUSE=0x1100c300 |
| |
| This is caused by IP0 getting handled by plat_irq_dispatch() rather than |
| its vectored interrupt handler, which is fixed by commit de856416e714 |
| ("MIPS: IRQ Stack: Fix erroneous jal to plat_irq_dispatch"). |
| |
| Fix plat_irq_dispatch() to handle non-vectored IPI interrupts correctly |
| by setting up IP2-6 as proper chained IRQ handlers and calling do_IRQ |
| for all MIPS CPU interrupts. |
| |
| Signed-off-by: Felix Fietkau <nbd@nbd.name> |
| Acked-by: John Crispin <john@phrozen.org> |
| Cc: linux-mips@linux-mips.org |
| Patchwork: https://patchwork.linux-mips.org/patch/15077/ |
| [james.hogan@imgtec.com: tweaked commit message] |
| Signed-off-by: James Hogan <james.hogan@imgtec.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c |
| index 8ac0e5994ed2..0ddf3698b85d 100644 |
| --- a/arch/mips/lantiq/irq.c |
| +++ b/arch/mips/lantiq/irq.c |
| @@ -269,6 +269,11 @@ static void ltq_hw5_irqdispatch(void) |
| DEFINE_HWx_IRQDISPATCH(5) |
| #endif |
| |
| +static void ltq_hw_irq_handler(struct irq_desc *desc) |
| +{ |
| + ltq_hw_irqdispatch(irq_desc_get_irq(desc) - 2); |
| +} |
| + |
| #ifdef CONFIG_MIPS_MT_SMP |
| void __init arch_init_ipiirq(int irq, struct irqaction *action) |
| { |
| @@ -313,23 +318,19 @@ static struct irqaction irq_call = { |
| asmlinkage void plat_irq_dispatch(void) |
| { |
| unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; |
| - unsigned int i; |
| - |
| - if ((MIPS_CPU_TIMER_IRQ == 7) && (pending & CAUSEF_IP7)) { |
| - do_IRQ(MIPS_CPU_TIMER_IRQ); |
| - goto out; |
| - } else { |
| - for (i = 0; i < MAX_IM; i++) { |
| - if (pending & (CAUSEF_IP2 << i)) { |
| - ltq_hw_irqdispatch(i); |
| - goto out; |
| - } |
| - } |
| + int irq; |
| + |
| + if (!pending) { |
| + spurious_interrupt(); |
| + return; |
| } |
| - pr_alert("Spurious IRQ: CAUSE=0x%08x\n", read_c0_status()); |
| |
| -out: |
| - return; |
| + pending >>= CAUSEB_IP; |
| + while (pending) { |
| + irq = fls(pending) - 1; |
| + do_IRQ(MIPS_CPU_IRQ_BASE + irq); |
| + pending &= ~BIT(irq); |
| + } |
| } |
| |
| static int icu_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) |
| @@ -354,11 +355,6 @@ static const struct irq_domain_ops irq_domain_ops = { |
| .map = icu_map, |
| }; |
| |
| -static struct irqaction cascade = { |
| - .handler = no_action, |
| - .name = "cascade", |
| -}; |
| - |
| int __init icu_of_init(struct device_node *node, struct device_node *parent) |
| { |
| struct device_node *eiu_node; |
| @@ -390,7 +386,7 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent) |
| mips_cpu_irq_init(); |
| |
| for (i = 0; i < MAX_IM; i++) |
| - setup_irq(i + 2, &cascade); |
| + irq_set_chained_handler(i + 2, ltq_hw_irq_handler); |
| |
| if (cpu_has_vint) { |
| pr_info("Setting up vectored interrupts\n"); |
| -- |
| 2.12.0 |
| |