public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [REGRESSION] threaded interrupt handler support breaks (some) irq handling on AVR32
@ 2009-04-14  5:46 Ben Nizette
  0 siblings, 0 replies; 10+ messages in thread
From: Ben Nizette @ 2009-04-14  5:46 UTC (permalink / raw)
  To: linux-kernel

[cc'ing *correct* lkml address]

After pulling in Linus' latest this morning, a tap on the touchscreen of
my AVR32-based board caused the system to hang hard.  It's an ads7843
touchscreen controller driven by drivers/input/touchscreen/ads7846.c -
the tap triggers a pen-down IRQ.  Note that I made a small mod to that
driver; due to limitations of the AVR32's gpio interrupt controller I
have to do

@@ -1129,7 +1129,7 @@ static int __devinit ads7846_probe(struct spi_device
*spi)

        ts->last_msg = m;

-       if (request_irq(spi->irq, ads7846_irq, IRQF_TRIGGER_FALLING,
+       if (request_irq(spi->irq, ads7846_irq, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
                        spi->dev.driver->name, ts)) {
                dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq);
                err = -EBUSY;

This doesn't effect the driver operation as the irq handler checks the
logic level of the line anyway.

I've bisected the problem to

commit 3aa551c9b4c40018f0e261a178e3d25478dc04a9
Author: Thomas Gleixner <tglx@linutronix.de>
Date:   Mon Mar 23 18:28:15 2009 +0100

    genirq: add threaded interrupt handler support

    Add support for threaded interrupt handlers:


Because this doesn't revert cleanly I did the bisection again just to be
sure and it came out the same.

Just before the hang,
~ # cat /proc/interrupts
           CPU0
  0:         42      intc  avr32_comparator
  1:          0      intc  atmel_lcdfb
  2:          1      intc  dw_dmac
  4:          4      intc  atmel_spi.1
  9:        555      intc  ttyS0
 21:          0      intc  rtc
 22:      34037      intc  tc_clkevt
 24:          0      intc  atmel_pwm
 25:       2439      intc  eth0
 28:        156      intc  atmel_mci.0
 31:          0      intc  atmel_usba_udc
131:          0      gpio  ads7846

Note it's that very last line which, when triggered, causes the hang.
As you can see, it's the only one connected through the gpio interrupt
chip.

No sysrq action is possible because of the limited kinds of terminals I
can attach to this board.

Given the limited scope for debug (no logs or sysrq output available) I
can't think exactly what more I can tell you to help you get to the
bottom of it.  I'll do whatever I can though, it's perfectly repeatable.

Thanks,
	--Ben.




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

* Re: [REGRESSION] threaded interrupt handler support breaks (some) irq handling on AVR32
       [not found] <1239685153.19815.12.camel@linux-51e8.site>
@ 2009-04-14  8:37 ` Ben Nizette
  2009-04-15  1:30   ` Ben Nizette
  0 siblings, 1 reply; 10+ messages in thread
From: Ben Nizette @ 2009-04-14  8:37 UTC (permalink / raw)
  To: tglx; +Cc: mingo, hskinnemoen, linux-kernel, kernel, imre.deak,
	David Brownell

On Tue, 2009-04-14 at 14:59 +1000, Ben Nizette wrote:

> Note it's that very last line which, when triggered, causes the hang.
> As you can see, it's the only one connected through the gpio interrupt
> chip.

Okhayy..  This is probably a red herring.  I just connected a button to
a gpio irq on that board and it sat there happily interrupting all night
long.

If anyone's reading with an ADS7846 on some other arch can they try to
reproduce?

If no one beats me to it i'll try and scatter printks and narrow down
exactly *where* it all explodes tomorrow.

Thx,
	--Ben.


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

* Re: [REGRESSION] threaded interrupt handler support breaks (some) irq handling on AVR32
  2009-04-14  8:37 ` [REGRESSION] threaded interrupt handler support breaks (some) irq handling on AVR32 Ben Nizette
@ 2009-04-15  1:30   ` Ben Nizette
  2009-04-15  7:57     ` Haavard Skinnemoen
  0 siblings, 1 reply; 10+ messages in thread
From: Ben Nizette @ 2009-04-15  1:30 UTC (permalink / raw)
  To: tglx; +Cc: David Brownell, hskinnemoen, kernel, linux-kernel, imre.deak,
	mingo

On Tue, 2009-04-14 at 18:37 +1000, Ben Nizette wrote:

> If no one beats me to it i'll try and scatter printks and narrow down
> exactly *where* it all explodes tomorrow.

static irqreturn_t ads7846_irq(int irq, void *handle)
{
	struct ads7846 *ts = handle;
	unsigned long flags;

	spin_lock_irqsave(&ts->lock, flags);
	if (likely(get_pendown_state(ts))) {
		if (!ts->irq_disabled) {
			/* The ARM do_simple_IRQ() dispatcher doesn't act
			 * like the other dispatchers:  it will report IRQs
			 * even after they've been disabled.  We work around
			 * that here.  (The "generic irq" framework may help...)
			 */
			ts->irq_disabled = 1;
			disable_irq(ts->spi->irq);
			ts->pending = 1;
			hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_DELAY),
					HRTIMER_MODE_REL);
		}
	}
	spin_unlock_irqrestore(&ts->lock, flags);

	return IRQ_HANDLED;
}

Right, a scattering of printks in there shows execution gets at least as
far as inside the inner-most code block.  A printk directly before the
disable_irq() doesn't make it to my console so I'm guessing that the
hang is in there somewhere.

Hope this helps,
	--Ben.




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

* Re: [REGRESSION] threaded interrupt handler support breaks (some) irq handling on AVR32
  2009-04-15  1:30   ` Ben Nizette
@ 2009-04-15  7:57     ` Haavard Skinnemoen
  2009-04-15  8:33       ` Haavard Skinnemoen
  2009-04-16  0:41       ` [PATCH] ads7846: fix unsafe disable_irq (was [REGRESSION] threaded interrupt handler support breaks (some) irq handling on AVR32) Ben Nizette
  0 siblings, 2 replies; 10+ messages in thread
From: Haavard Skinnemoen @ 2009-04-15  7:57 UTC (permalink / raw)
  To: Ben Nizette
  Cc: tglx, David Brownell, hskinnemoen, kernel, linux-kernel,
	imre.deak, mingo

Ben Nizette wrote:
> static irqreturn_t ads7846_irq(int irq, void *handle)
> {
> 	struct ads7846 *ts = handle;
> 	unsigned long flags;
> 
> 	spin_lock_irqsave(&ts->lock, flags);
> 	if (likely(get_pendown_state(ts))) {
> 		if (!ts->irq_disabled) {
> 			/* The ARM do_simple_IRQ() dispatcher doesn't act
> 			 * like the other dispatchers:  it will report IRQs
> 			 * even after they've been disabled.  We work around
> 			 * that here.  (The "generic irq" framework may help...)
> 			 */
> 			ts->irq_disabled = 1;
> 			disable_irq(ts->spi->irq);

Shouldn't that be disable_irq_nosync()?

Haavard

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

* Re: [REGRESSION] threaded interrupt handler support breaks (some) irq handling on AVR32
  2009-04-15  7:57     ` Haavard Skinnemoen
@ 2009-04-15  8:33       ` Haavard Skinnemoen
  2009-04-15 16:01         ` Bill Gatliff
  2009-04-16  0:41       ` [PATCH] ads7846: fix unsafe disable_irq (was [REGRESSION] threaded interrupt handler support breaks (some) irq handling on AVR32) Ben Nizette
  1 sibling, 1 reply; 10+ messages in thread
From: Haavard Skinnemoen @ 2009-04-15  8:33 UTC (permalink / raw)
  To: Ben Nizette; +Cc: tglx, David Brownell, kernel, linux-kernel, imre.deak, mingo

Haavard Skinnemoen wrote:
> Ben Nizette wrote:
> > static irqreturn_t ads7846_irq(int irq, void *handle)
> > {
> > 	struct ads7846 *ts = handle;
> > 	unsigned long flags;
> > 
> > 	spin_lock_irqsave(&ts->lock, flags);
> > 	if (likely(get_pendown_state(ts))) {
> > 		if (!ts->irq_disabled) {
> > 			/* The ARM do_simple_IRQ() dispatcher doesn't act
> > 			 * like the other dispatchers:  it will report IRQs
> > 			 * even after they've been disabled.  We work around
> > 			 * that here.  (The "generic irq" framework may help...)
> > 			 */
> > 			ts->irq_disabled = 1;
> > 			disable_irq(ts->spi->irq);  
> 
> Shouldn't that be disable_irq_nosync()?

Ok, simply stating that without providing an explanation was probably
not so helpful...

I think the problem is that disable_irq() calls synchronize_irq(),
which waits until the corresponding interrupt handler is no longer
running on any CPU. And since we're calling it from the interrupt
handler, we'll have a deadlock because the interrupt handler won't
return until synchronize_irq() returns, and that won't happen until the
interrupt handler returns and so on.

So I think changing disable_irq() into disable_irq_nosync() (which
doesn't call synchronize_irq()) will fix it, though I'm not sure what
difference the threaded interrupt handling code makes -- AFAICT, this
code has always been dangerous.

Haavard

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

* Re: [REGRESSION] threaded interrupt handler support breaks (some) irq handling on AVR32
  2009-04-15  8:33       ` Haavard Skinnemoen
@ 2009-04-15 16:01         ` Bill Gatliff
  2009-04-16  8:40           ` Haavard Skinnemoen
  0 siblings, 1 reply; 10+ messages in thread
From: Bill Gatliff @ 2009-04-15 16:01 UTC (permalink / raw)
  To: Haavard Skinnemoen
  Cc: Ben Nizette, imre.deak, kernel, linux-kernel, David Brownell,
	tglx, mingo

Haavard Skinnemoen wrote:
> AFAICT, this code has always been dangerous.
>   

Can you propose a better way to handle the problem?  It's a case that 
crops up with a lot of touch screen controllers.


b.g.

-- 
Bill Gatliff
bgat@billgatliff.com


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

* [PATCH] ads7846: fix unsafe disable_irq (was [REGRESSION] threaded interrupt handler support breaks (some) irq handling on AVR32)
  2009-04-15  7:57     ` Haavard Skinnemoen
  2009-04-15  8:33       ` Haavard Skinnemoen
@ 2009-04-16  0:41       ` Ben Nizette
  2009-04-16  1:58         ` Dmitry Torokhov
  1 sibling, 1 reply; 10+ messages in thread
From: Ben Nizette @ 2009-04-16  0:41 UTC (permalink / raw)
  To: dmitry.torokhov
  Cc: tglx, David Brownell, hskinnemoen, kernel, linux-kernel,
	imre.deak, mingo, Bill Gatliff, Haavard Skinnemoen

On Wed, 2009-04-15 at 09:57 +0200, Haavard Skinnemoen wrote:
> Shouldn't that be disable_irq_nosync()?

Indeed, good catch.  That fixes it.

--------------8<--------------------

The use of disable_irq inside the handler for the interrupt being
disabled has always been dangerous.  disable_irq should wait for that
handler to complete before returning -> deadlock.

For some reason this wasn't actually the case until 3aa551c9b was merged
but since this time, the ads7846 driver has deadlocked the system on
first interrupt.

Convert the driver to use the handler-safe _nosync variant.

Signed-off-by: Ben Nizette <bn@niasdigital.com>

---

diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index 61b4a02..f2513e6 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -746,7 +746,7 @@ static irqreturn_t ads7846_irq(int irq, void *handle)
 			 * that here.  (The "generic irq" framework may help...)
 			 */
 			ts->irq_disabled = 1;
-			disable_irq(ts->spi->irq);
+			disable_irq_nosync(ts->spi->irq);
 			ts->pending = 1;
 			hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_DELAY),
 					HRTIMER_MODE_REL);



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

* Re: [PATCH] ads7846: fix unsafe disable_irq (was [REGRESSION] threaded interrupt handler support breaks (some) irq handling on AVR32)
  2009-04-16  0:41       ` [PATCH] ads7846: fix unsafe disable_irq (was [REGRESSION] threaded interrupt handler support breaks (some) irq handling on AVR32) Ben Nizette
@ 2009-04-16  1:58         ` Dmitry Torokhov
  0 siblings, 0 replies; 10+ messages in thread
From: Dmitry Torokhov @ 2009-04-16  1:58 UTC (permalink / raw)
  To: Ben Nizette
  Cc: tglx, David Brownell, hskinnemoen, kernel, linux-kernel,
	imre.deak, mingo, Bill Gatliff, Haavard Skinnemoen

On Thu, Apr 16, 2009 at 10:41:57AM +1000, Ben Nizette wrote:
> On Wed, 2009-04-15 at 09:57 +0200, Haavard Skinnemoen wrote:
> > Shouldn't that be disable_irq_nosync()?
> 
> Indeed, good catch.  That fixes it.
> 
> --------------8<--------------------
> 
> The use of disable_irq inside the handler for the interrupt being
> disabled has always been dangerous.  disable_irq should wait for that
> handler to complete before returning -> deadlock.
> 
> For some reason this wasn't actually the case until 3aa551c9b was merged
> but since this time, the ads7846 driver has deadlocked the system on
> first interrupt.
> 
> Convert the driver to use the handler-safe _nosync variant.
> 

Applied, thank you very much Ben.

-- 
Dmitry

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

* Re: [REGRESSION] threaded interrupt handler support breaks (some) irq handling on AVR32
  2009-04-15 16:01         ` Bill Gatliff
@ 2009-04-16  8:40           ` Haavard Skinnemoen
  2009-04-16 13:25             ` Bill Gatliff
  0 siblings, 1 reply; 10+ messages in thread
From: Haavard Skinnemoen @ 2009-04-16  8:40 UTC (permalink / raw)
  To: Bill Gatliff
  Cc: Ben Nizette, imre.deak, kernel, linux-kernel, David Brownell,
	tglx, mingo

Bill Gatliff wrote:
> Haavard Skinnemoen wrote:
> > AFAICT, this code has always been dangerous.
> >     
> 
> Can you propose a better way to handle the problem?  It's a case that 
> crops up with a lot of touch screen controllers.

I thought I already did: Use disable_irq_nosync() instead.

Haavard

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

* Re: [REGRESSION] threaded interrupt handler support breaks (some) irq handling on AVR32
  2009-04-16  8:40           ` Haavard Skinnemoen
@ 2009-04-16 13:25             ` Bill Gatliff
  0 siblings, 0 replies; 10+ messages in thread
From: Bill Gatliff @ 2009-04-16 13:25 UTC (permalink / raw)
  To: Haavard Skinnemoen
  Cc: Ben Nizette, imre.deak, kernel, linux-kernel, David Brownell,
	tglx, mingo

Haavard Skinnemoen wrote:
> Bill Gatliff wrote:
>   
>> Haavard Skinnemoen wrote:
>>     
>>> AFAICT, this code has always been dangerous.
>>>     
>>>       
>> Can you propose a better way to handle the problem?  It's a case that 
>> crops up with a lot of touch screen controllers.
>>     
>
> I thought I already did: Use disable_irq_nosync() instead.
>   

Aah.  I misinterpreted what you wrote.  Thanks!


b.g.

-- 
Bill Gatliff
bgat@billgatliff.com


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

end of thread, other threads:[~2009-04-16 13:25 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <1239685153.19815.12.camel@linux-51e8.site>
2009-04-14  8:37 ` [REGRESSION] threaded interrupt handler support breaks (some) irq handling on AVR32 Ben Nizette
2009-04-15  1:30   ` Ben Nizette
2009-04-15  7:57     ` Haavard Skinnemoen
2009-04-15  8:33       ` Haavard Skinnemoen
2009-04-15 16:01         ` Bill Gatliff
2009-04-16  8:40           ` Haavard Skinnemoen
2009-04-16 13:25             ` Bill Gatliff
2009-04-16  0:41       ` [PATCH] ads7846: fix unsafe disable_irq (was [REGRESSION] threaded interrupt handler support breaks (some) irq handling on AVR32) Ben Nizette
2009-04-16  1:58         ` Dmitry Torokhov
2009-04-14  5:46 [REGRESSION] threaded interrupt handler support breaks (some) irq handling on AVR32 Ben Nizette

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox