2006-12-10 16:36:46

by Daniel Walker

[permalink] [raw]
Subject: [PATCH -rt][RESEND] fix preempt hardirqs on OMAP

This should fix hardirq threading when the chained handler disables an interrupt
while setting IRQ_PENDING. Which happens on ARM OMAP. It also has the effect of
re-running the interrupt on IRQ_PENDING, which would normally be handled inside
the chained handler. Since this happens inside a thread the chained handler will
just wake up the thread multiple times, leaving the thread to actually rerun the
interrupt.

Signed-Off-By: Daniel Walker <[email protected]>

---
kernel/irq/manage.c | 14 ++++++++++++++
1 files changed, 14 insertions(+)

Index: linux-2.6.19/kernel/irq/manage.c
===================================================================
--- linux-2.6.19.orig/kernel/irq/manage.c
+++ linux-2.6.19/kernel/irq/manage.c
@@ -546,6 +546,7 @@ static void thread_simple_irq(irq_desc_t
unsigned int irq = desc - irq_desc;
irqreturn_t action_ret;

+restart:
if (action && !desc->depth) {
spin_unlock(&desc->lock);
action_ret = handle_IRQ_event(irq, action);
@@ -555,6 +556,19 @@ static void thread_simple_irq(irq_desc_t
if (!noirqdebug)
note_interrupt(irq, desc, action_ret);
}
+
+ /*
+ * Some boards will disable an interrupt when it
+ * sets IRQ_PENDING . So we have to remove the flag
+ * and re-enable to handle it.
+ */
+ if (desc->status & IRQ_PENDING) {
+ desc->status &= ~IRQ_PENDING;
+ if (desc->chip)
+ desc->chip->enable(irq);
+ goto restart;
+ }
+
desc->status &= ~IRQ_INPROGRESS;
}

--


2006-12-11 19:07:34

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH -rt][RESEND] fix preempt hardirqs on OMAP


* Daniel Walker <[email protected]> wrote:

> + /*
> + * Some boards will disable an interrupt when it
> + * sets IRQ_PENDING . So we have to remove the flag
> + * and re-enable to handle it.
> + */
> + if (desc->status & IRQ_PENDING) {
> + desc->status &= ~IRQ_PENDING;
> + if (desc->chip)
> + desc->chip->enable(irq);
> + goto restart;
> + }

what if the irq got disabled meanwhile? Also, chip->enable is a
compatibility method, not something we should use in a flow handler.

Ingo

2006-12-11 19:38:31

by Daniel Walker

[permalink] [raw]
Subject: Re: [PATCH -rt][RESEND] fix preempt hardirqs on OMAP

On Mon, 2006-12-11 at 20:05 +0100, Ingo Molnar wrote:
> * Daniel Walker <[email protected]> wrote:
>
> > + /*
> > + * Some boards will disable an interrupt when it
> > + * sets IRQ_PENDING . So we have to remove the flag
> > + * and re-enable to handle it.
> > + */
> > + if (desc->status & IRQ_PENDING) {
> > + desc->status &= ~IRQ_PENDING;
> > + if (desc->chip)
> > + desc->chip->enable(irq);
> > + goto restart;
> > + }
>
> what if the irq got disabled meanwhile? Also, chip->enable is a
> compatibility method, not something we should use in a flow handler.

I don't know how other arches deal with IRQ_PENDING, but ARM (OMAP at
least) disables the IRQ on IRQ_PENDING. The problem is that by threading
the IRQ we take some control away from the low level code, which needs
to be replaced.

I'm open to potentially removing the irq disable()->enable() cycle on
IRQ_PENDING if it's only done on OMAP. My feeling is that it's in other
ARM's which would make that change more invasive, but I haven't actually
researched that.

Daniel


2006-12-11 19:53:46

by Tony Lindgren

[permalink] [raw]
Subject: Re: [PATCH -rt][RESEND] fix preempt hardirqs on OMAP

Hi,

* Daniel Walker <[email protected]> [061211 11:41]:
> On Mon, 2006-12-11 at 20:05 +0100, Ingo Molnar wrote:
> > * Daniel Walker <[email protected]> wrote:
> >
> > > + /*
> > > + * Some boards will disable an interrupt when it
> > > + * sets IRQ_PENDING . So we have to remove the flag
> > > + * and re-enable to handle it.
> > > + */
> > > + if (desc->status & IRQ_PENDING) {
> > > + desc->status &= ~IRQ_PENDING;
> > > + if (desc->chip)
> > > + desc->chip->enable(irq);
> > > + goto restart;
> > > + }
> >
> > what if the irq got disabled meanwhile? Also, chip->enable is a
> > compatibility method, not something we should use in a flow handler.
>
> I don't know how other arches deal with IRQ_PENDING, but ARM (OMAP at
> least) disables the IRQ on IRQ_PENDING. The problem is that by threading
> the IRQ we take some control away from the low level code, which needs
> to be replaced.
>
> I'm open to potentially removing the irq disable()->enable() cycle on
> IRQ_PENDING if it's only done on OMAP. My feeling is that it's in other
> ARM's which would make that change more invasive, but I haven't actually
> researched that.

Hmm, I wonder if this is just legacy left over from earlier when
set_irq_type() was used and the flags not passed with request_irq().
This was causing some omap gpio interrupts to trigger immediately
after request_irq().

Regards,

Tony

2006-12-11 19:54:16

by Russell King

[permalink] [raw]
Subject: Re: [PATCH -rt][RESEND] fix preempt hardirqs on OMAP

On Mon, Dec 11, 2006 at 11:38:28AM -0800, Daniel Walker wrote:
> On Mon, 2006-12-11 at 20:05 +0100, Ingo Molnar wrote:
> > * Daniel Walker <[email protected]> wrote:
> >
> > > + /*
> > > + * Some boards will disable an interrupt when it
> > > + * sets IRQ_PENDING . So we have to remove the flag
> > > + * and re-enable to handle it.
> > > + */
> > > + if (desc->status & IRQ_PENDING) {
> > > + desc->status &= ~IRQ_PENDING;
> > > + if (desc->chip)
> > > + desc->chip->enable(irq);
> > > + goto restart;
> > > + }
> >
> > what if the irq got disabled meanwhile? Also, chip->enable is a
> > compatibility method, not something we should use in a flow handler.
>
> I don't know how other arches deal with IRQ_PENDING, but ARM (OMAP at
> least) disables the IRQ on IRQ_PENDING.

Please point out where it's doing that, and I'll take a look to see
if it's doing something it shouldn't.

--
Russell King
Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/
maintainer of:

2006-12-11 19:59:29

by Daniel Walker

[permalink] [raw]
Subject: Re: [PATCH -rt][RESEND] fix preempt hardirqs on OMAP

On Mon, 2006-12-11 at 19:54 +0000, Russell King wrote:

> > > what if the irq got disabled meanwhile? Also, chip->enable is a
> > > compatibility method, not something we should use in a flow handler.
> >
> > I don't know how other arches deal with IRQ_PENDING, but ARM (OMAP at
> > least) disables the IRQ on IRQ_PENDING.
>
> Please point out where it's doing that, and I'll take a look to see
> if it's doing something it shouldn't.

It's in arch/arm/plat-omap/gpio.c . It uses the lowlevel function to
disable the interrupt, not chip->disable() . In gpio_irq_handler() .

Daniel