All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH/RFC] rtc: rtc-twl: Fixed nested IRQ handling in resume from suspend
@ 2014-09-13 11:19 Laurent Pinchart
  2014-09-13 19:12 ` Thomas Gleixner
  2014-09-17 21:57 ` Thomas Gleixner
  0 siblings, 2 replies; 6+ messages in thread
From: Laurent Pinchart @ 2014-09-13 11:19 UTC (permalink / raw)
  To: linux-kernel
  Cc: rtc-linux, Rafael J. Wysocki, Thomas Gleixner, laurent.pinchart

The TWL RTC interrupt is a double-nested threaded interrupt, handled
through the TWL SIH (Secondary Interrupt Handler) and PIH (Primary
Interrupt Handler).

When the system is woken up from suspend by a TWL RTC alarm interrupt,
the TWL PIH and SIH are enabled first (due to the normal IRQ enabling
sequence for the PIH and to the IRQF_EARLY_RESUME flag for the SIH)
before the TWL RTC interrupt gets enabled. This results on the interrupt
being processed by the TWL primary interrupt handler, forwarded to the
nested SIH, and then marked as pending for the RTC by handle_nested_irq
called from the SIH.

The RTC interrupt then eventually gets reenabled the kernel, which will
try to call its top half interrupt handler. As the interrupt is a nested
threaded IRQ, its primary handler has been set to the
irq_nested_primary_handler function, which is never supposed to be
called and generates a WARN_ON, without waking the IRQ thread up.

Fix this by setting the IRQF_EARLY_RESUME for the TWL RTC interrupt to
ensure it gets enabled before the parent handlers try to process it.

This is likely a bit of a hack, I have a feeling that a more generic
solution that would fix the problem for all nested threaded IRQs enabled
as a wake up source by enable_irq_wake would be better.

I've noticed that Rafael's "PM / sleep / irq: Do not suspend wakeup
interrupts" patch (which has been reverted) might be related, but it
resulted in an endless stream of I2C errors in the kernel log at resume
time:

[  189.730682] twl4030: I2C error -13 reading PIH ISR
[  189.730712] twl: Read failed (mod 1, reg 0x01 count 1)

Given that I'm not that familiar with the IRQ subsystem I would
appreciate some guidance on how to properly solve the problem.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/rtc/rtc-twl.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c
index 1915464..3155af1 100644
--- a/drivers/rtc/rtc-twl.c
+++ b/drivers/rtc/rtc-twl.c
@@ -536,7 +536,8 @@ static int twl_rtc_probe(struct platform_device *pdev)
 
 	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
 					twl_rtc_interrupt,
-					IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+					IRQF_TRIGGER_RISING | IRQF_ONESHOT |
+					IRQF_EARLY_RESUME,
 					dev_name(&rtc->dev), rtc);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "IRQ is not free.\n");
-- 
Regards,

Laurent Pinchart


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2015-02-26 13:12 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-09-13 11:19 [PATCH/RFC] rtc: rtc-twl: Fixed nested IRQ handling in resume from suspend Laurent Pinchart
2014-09-13 19:12 ` Thomas Gleixner
2014-09-14 23:41   ` Laurent Pinchart
2014-09-17 21:57 ` Thomas Gleixner
2014-09-21  1:04   ` Rafael J. Wysocki
2015-02-26 13:05   ` Gerlando Falauto

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.