Message ID | 20200318170904.1461278-1-mans0n@gorani.run (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | irqchip/versatile-fpga: Handle chained IRQs properly | expand |
Hi Sungbo, On 2020-03-18 17:09, Sungbo Eo wrote: > 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. Nice catch. > > Signed-off-by: Sungbo Eo <mans0n@gorani.run> > Cc: Neil Armstrong <narmstrong@baylibre.com> > --- > drivers/irqchip/irq-versatile-fpga.c | 9 ++++++++- > 1 file changed, 8 insertions(+), 1 deletion(-) > > diff --git a/drivers/irqchip/irq-versatile-fpga.c > b/drivers/irqchip/irq-versatile-fpga.c > index 928858dada75..08faab2fec3e 100644 > --- a/drivers/irqchip/irq-versatile-fpga.c > +++ b/drivers/irqchip/irq-versatile-fpga.c > @@ -6,6 +6,7 @@ > #include <linux/irq.h> > #include <linux/io.h> > #include <linux/irqchip.h> > +#include <linux/irqchip/chained_irq.h> > #include <linux/irqchip/versatile-fpga.h> > #include <linux/irqdomain.h> > #include <linux/module.h> > @@ -68,12 +69,15 @@ static void fpga_irq_unmask(struct irq_data *d) > > 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); > u32 status = readl(f->base + IRQ_STATUS); > > + chained_irq_enter(chip, desc); > + It's probably not a big deal, but I'm not fond of starting talking to the muxing irqchip before having done the chained_irq_enter() call. Moving that read here would probably be safer. > if (status == 0) { > do_bad_IRQ(desc); > - return; > + goto out; > } > > do { > @@ -82,6 +86,9 @@ static void fpga_irq_handle(struct irq_desc *desc) > status &= ~(1 << irq); > generic_handle_irq(irq_find_mapping(f->domain, irq)); > } while (status); > + > +out: > + chained_irq_exit(chip, desc); > } > > /* Otherwise looks good. If you send it again with the above fixed and a Fixes: tag, I'll queue it. Thanks, M.
Hi Marc, On 2020-03-19 02:48, Marc Zyngier wrote: > Hi Sungbo, > > On 2020-03-18 17:09, Sungbo Eo wrote: >> 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. > > Nice catch. > >> >> Signed-off-by: Sungbo Eo <mans0n@gorani.run> >> Cc: Neil Armstrong <narmstrong@baylibre.com> >> --- >> drivers/irqchip/irq-versatile-fpga.c | 9 ++++++++- >> 1 file changed, 8 insertions(+), 1 deletion(-) >> >> diff --git a/drivers/irqchip/irq-versatile-fpga.c >> b/drivers/irqchip/irq-versatile-fpga.c >> index 928858dada75..08faab2fec3e 100644 >> --- a/drivers/irqchip/irq-versatile-fpga.c >> +++ b/drivers/irqchip/irq-versatile-fpga.c >> @@ -6,6 +6,7 @@ >> #include <linux/irq.h> >> #include <linux/io.h> >> #include <linux/irqchip.h> >> +#include <linux/irqchip/chained_irq.h> >> #include <linux/irqchip/versatile-fpga.h> >> #include <linux/irqdomain.h> >> #include <linux/module.h> >> @@ -68,12 +69,15 @@ static void fpga_irq_unmask(struct irq_data *d) >> >> 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); >> u32 status = readl(f->base + IRQ_STATUS); >> >> + chained_irq_enter(chip, desc); >> + > > It's probably not a big deal, but I'm not fond of starting talking to > the muxing irqchip before having done the chained_irq_enter() call. > > Moving that read here would probably be safer. Oops, I missed it. Thanks for pointing it out. > >> if (status == 0) { >> do_bad_IRQ(desc); >> - return; >> + goto out; >> } >> >> do { >> @@ -82,6 +86,9 @@ static void fpga_irq_handle(struct irq_desc *desc) >> status &= ~(1 << irq); >> generic_handle_irq(irq_find_mapping(f->domain, irq)); >> } while (status); >> + >> +out: >> + chained_irq_exit(chip, desc); >> } >> >> /* > > Otherwise looks good. If you send it again with the above fixed > and a Fixes: tag, I'll queue it. It seems the handler had been broken from the very beginning. Could you give me a hint on how the tag should be like? Thanks. > > Thanks, > > M.
On 2020-03-18 18:20, Sungbo Eo wrote: > Hi Marc, > > On 2020-03-19 02:48, Marc Zyngier wrote: >> Hi Sungbo, >> >> On 2020-03-18 17:09, Sungbo Eo wrote: >>> 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. >> >> Nice catch. >> >>> >>> Signed-off-by: Sungbo Eo <mans0n@gorani.run> >>> Cc: Neil Armstrong <narmstrong@baylibre.com> >>> --- >>> drivers/irqchip/irq-versatile-fpga.c | 9 ++++++++- >>> 1 file changed, 8 insertions(+), 1 deletion(-) >>> >>> diff --git a/drivers/irqchip/irq-versatile-fpga.c >>> b/drivers/irqchip/irq-versatile-fpga.c >>> index 928858dada75..08faab2fec3e 100644 >>> --- a/drivers/irqchip/irq-versatile-fpga.c >>> +++ b/drivers/irqchip/irq-versatile-fpga.c >>> @@ -6,6 +6,7 @@ >>> #include <linux/irq.h> >>> #include <linux/io.h> >>> #include <linux/irqchip.h> >>> +#include <linux/irqchip/chained_irq.h> >>> #include <linux/irqchip/versatile-fpga.h> >>> #include <linux/irqdomain.h> >>> #include <linux/module.h> >>> @@ -68,12 +69,15 @@ static void fpga_irq_unmask(struct irq_data *d) >>> >>> 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); >>> u32 status = readl(f->base + IRQ_STATUS); >>> >>> + chained_irq_enter(chip, desc); >>> + >> >> It's probably not a big deal, but I'm not fond of starting talking to >> the muxing irqchip before having done the chained_irq_enter() call. >> >> Moving that read here would probably be safer. > > Oops, I missed it. Thanks for pointing it out. > >> >>> if (status == 0) { >>> do_bad_IRQ(desc); >>> - return; >>> + goto out; >>> } >>> >>> do { >>> @@ -82,6 +86,9 @@ static void fpga_irq_handle(struct irq_desc *desc) >>> status &= ~(1 << irq); >>> generic_handle_irq(irq_find_mapping(f->domain, irq)); >>> } while (status); >>> + >>> +out: >>> + chained_irq_exit(chip, desc); >>> } >>> >>> /* >> >> Otherwise looks good. If you send it again with the above fixed >> and a Fixes: tag, I'll queue it. > > It seems the handler had been broken from the very beginning. Could > you give me a hint on how the tag should be like? Indeed, it has been broken forever. I'm tempted to say: Fixes: c41b16f8c9d9d ("ARM: integrator/versatile: consolidate FPGA IRQ handling code") even if it probably predates the introduction of the chained_irq_enter() helpers. This will ensure this gets backported to older kernels... Thanks, M.
diff --git a/drivers/irqchip/irq-versatile-fpga.c b/drivers/irqchip/irq-versatile-fpga.c index 928858dada75..08faab2fec3e 100644 --- a/drivers/irqchip/irq-versatile-fpga.c +++ b/drivers/irqchip/irq-versatile-fpga.c @@ -6,6 +6,7 @@ #include <linux/irq.h> #include <linux/io.h> #include <linux/irqchip.h> +#include <linux/irqchip/chained_irq.h> #include <linux/irqchip/versatile-fpga.h> #include <linux/irqdomain.h> #include <linux/module.h> @@ -68,12 +69,15 @@ static void fpga_irq_unmask(struct irq_data *d) 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); u32 status = readl(f->base + IRQ_STATUS); + chained_irq_enter(chip, desc); + if (status == 0) { do_bad_IRQ(desc); - return; + goto out; } do { @@ -82,6 +86,9 @@ static void fpga_irq_handle(struct irq_desc *desc) status &= ~(1 << irq); generic_handle_irq(irq_find_mapping(f->domain, irq)); } while (status); + +out: + chained_irq_exit(chip, desc); } /*
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. Signed-off-by: Sungbo Eo <mans0n@gorani.run> Cc: Neil Armstrong <narmstrong@baylibre.com> --- drivers/irqchip/irq-versatile-fpga.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)