irqchip/versatile-fpga: Handle chained IRQs properly
Enclose the chained handler with chained_irq_{enter,exit}(), so that the muxed interrupts get properly acked. This patch also fixes a reboot bug on OX820 SoC, where the jiffies timer interrupt is never acked. The kernel waits a clock tick forever in calibrate_delay_converge(), which leads to a boot hang. Fixes: c41b16f8c9d9 ("ARM: integrator/versatile: consolidate FPGA IRQ handling code") Signed-off-by: Sungbo Eo <mans0n@gorani.run> Signed-off-by: Marc Zyngier <maz@kernel.org> Link: https://lore.kernel.org/r/20200319023448.1479701-1-mans0n@gorani.run
This commit is contained in:
parent
7809f7011c
commit
486562da59
@ -6,6 +6,7 @@
|
|||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/irqchip.h>
|
#include <linux/irqchip.h>
|
||||||
|
#include <linux/irqchip/chained_irq.h>
|
||||||
#include <linux/irqchip/versatile-fpga.h>
|
#include <linux/irqchip/versatile-fpga.h>
|
||||||
#include <linux/irqdomain.h>
|
#include <linux/irqdomain.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
@ -68,12 +69,16 @@ static void fpga_irq_unmask(struct irq_data *d)
|
|||||||
|
|
||||||
static void fpga_irq_handle(struct irq_desc *desc)
|
static void fpga_irq_handle(struct irq_desc *desc)
|
||||||
{
|
{
|
||||||
|
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||||
struct fpga_irq_data *f = irq_desc_get_handler_data(desc);
|
struct fpga_irq_data *f = irq_desc_get_handler_data(desc);
|
||||||
u32 status = readl(f->base + IRQ_STATUS);
|
u32 status;
|
||||||
|
|
||||||
|
chained_irq_enter(chip, desc);
|
||||||
|
|
||||||
|
status = readl(f->base + IRQ_STATUS);
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
do_bad_IRQ(desc);
|
do_bad_IRQ(desc);
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@ -82,6 +87,9 @@ static void fpga_irq_handle(struct irq_desc *desc)
|
|||||||
status &= ~(1 << irq);
|
status &= ~(1 << irq);
|
||||||
generic_handle_irq(irq_find_mapping(f->domain, irq));
|
generic_handle_irq(irq_find_mapping(f->domain, irq));
|
||||||
} while (status);
|
} while (status);
|
||||||
|
|
||||||
|
out:
|
||||||
|
chained_irq_exit(chip, desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user