public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* IRQF_DISABLED problem
@ 2007-07-26 20:13 Matthew Wilcox
  2007-07-26 20:41 ` Linus Torvalds
  2007-07-26 22:23 ` David Miller
  0 siblings, 2 replies; 10+ messages in thread
From: Matthew Wilcox @ 2007-07-26 20:13 UTC (permalink / raw)
  To: Ingo Molnar, linux-kernel; +Cc: Linus Torvalds


I noticed that we only look at the first action in the chain when
determining whether to re-enable local interrupts during handle_IRQ_event.
But we don't try to exclude sharing interrupts with mixtures of
IRQF_DISABLED set and clear.  I just tried to do that locally, and one
of my USB ports disappears, because it shares an interrupt with qla2xxx
which sets IRQF_DISABLED, and UHCI doesn't.

Another possibility is to force it if *any* of the handlers want
IRQF_DISABLED.  This seems to work:

diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 203a518..d804a0b 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -308,6 +308,15 @@ int setup_irq(unsigned int irq, struct irqaction *new)
 			goto mismatch;
 #endif
 
+		/* If one handler wants interrupts to be disabled,
+		 * they must all be disabled.  Rather than walk the list of
+		 * handlers twice at interrupt time, just make sure the
+		 * head handler has its flag set
+		 */
+		if ((new->flags & IRQF_DISABLED) &&
+		    !(old->flags & IRQF_DISABLED)
+			old->flags |= IRQF_DISABLED);
+
 		/* add new interrupt at end of irq queue */
 		do {
 			p = &old->next;


This patch makes interrupts requested with IRQF_DISABLED non-matching
fail, in case you think it's a better solution:

diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 203a518..2c99b88 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -293,10 +293,12 @@ int setup_irq(unsigned int irq, struct irqaction *new)
 		 * Can't share interrupts unless both agree to and are
 		 * the same type (level, edge, polarity). So both flag
 		 * fields must have IRQF_SHARED set and the bits which
-		 * set the trigger type must match.
+		 * set the trigger type must match and the disabled bit
+		 * must match.
 		 */
 		if (!((old->flags & new->flags) & IRQF_SHARED) ||
-		    ((old->flags ^ new->flags) & IRQF_TRIGGER_MASK)) {
+		    ((old->flags ^ new->flags) &
+		     (IRQF_TRIGGER_MASK | IRQF_DISABLED))) {
 			old_name = old->name;
 			goto mismatch;
 		}

-- 
"Bill, look, we understand that you're interested in selling us this
operating system, but compare it to ours.  We can't possibly take such
a retrograde step."

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

* Re: IRQF_DISABLED problem
  2007-07-26 20:13 Matthew Wilcox
@ 2007-07-26 20:41 ` Linus Torvalds
  2007-07-26 22:23 ` David Miller
  1 sibling, 0 replies; 10+ messages in thread
From: Linus Torvalds @ 2007-07-26 20:41 UTC (permalink / raw)
  To: Matthew Wilcox; +Cc: Ingo Molnar, linux-kernel



On Thu, 26 Jul 2007, Matthew Wilcox wrote:
> 
> I noticed that we only look at the first action in the chain when
> determining whether to re-enable local interrupts during handle_IRQ_event.

You can't really share an interrupt handler that wants to run with 
interrupts on with one that wants to run with them off.

That said, I think the whole IRQF_DISABLED thing should go away. It is 
total legacy crud, methinks - it used to be SA_INTERRUPT, and it's always 
worked the way IRQF_DISABLED works now: it only looks at the first one in 
the chain.

> But we don't try to exclude sharing interrupts with mixtures of
> IRQF_DISABLED set and clear.

I think you should just consider it to be a "if you mix them, you get 
randomr results".

> I just tried to do that locally, and one
> of my USB ports disappears, because it shares an interrupt with qla2xxx
> which sets IRQF_DISABLED, and UHCI doesn't.

There really is no excuse for using IRQF_DISABLED unless you're something 
like a system device (like the timer interrupt or similar) and you have an 
exclusive irq handler. A SCSI driver almost certainly has no business 
doing it.

Generally, I would say that "IRQF_DISABLED | IRQF_SHARED" is an insane 
combination, but a quick grep shows that it's distressingly common.

The real fix is to just leave it as it is. It's always worked that way. 
IRQF_DISABLED basically cannot have any sane behaviour in the presense of 
mixing.

		Linus

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

* Re: IRQF_DISABLED problem
  2007-07-26 20:13 Matthew Wilcox
  2007-07-26 20:41 ` Linus Torvalds
@ 2007-07-26 22:23 ` David Miller
  2007-07-26 23:04   ` Linus Torvalds
  1 sibling, 1 reply; 10+ messages in thread
From: David Miller @ 2007-07-26 22:23 UTC (permalink / raw)
  To: matthew; +Cc: mingo, linux-kernel, torvalds

From: Matthew Wilcox <matthew@wil.cx>
Date: Thu, 26 Jul 2007 14:13:56 -0600

> 
> I noticed that we only look at the first action in the chain when
> determining whether to re-enable local interrupts during handle_IRQ_event.
> But we don't try to exclude sharing interrupts with mixtures of
> IRQF_DISABLED set and clear.  I just tried to do that locally, and one
> of my USB ports disappears, because it shares an interrupt with qla2xxx
> which sets IRQF_DISABLED, and UHCI doesn't.
> 
> Another possibility is to force it if *any* of the handlers want
> IRQF_DISABLED.  This seems to work:

Yes, this is consistent with how we handle sharing, we should
enforce that all the flags on the chain are compatible.

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

* Re: IRQF_DISABLED problem
  2007-07-26 22:23 ` David Miller
@ 2007-07-26 23:04   ` Linus Torvalds
  2007-07-26 23:14     ` David Miller
  2007-07-26 23:17     ` Linus Torvalds
  0 siblings, 2 replies; 10+ messages in thread
From: Linus Torvalds @ 2007-07-26 23:04 UTC (permalink / raw)
  To: David Miller; +Cc: matthew, mingo, linux-kernel



On Thu, 26 Jul 2007, David Miller wrote:
> > 
> > Another possibility is to force it if *any* of the handlers want
> > IRQF_DISABLED.  This seems to work:
> 
> Yes, this is consistent with how we handle sharing, we should
> enforce that all the flags on the chain are compatible.

No. It's no better than the current situation.

There are really a few choices:

 (a) Keep it like we always have.  What's the downside, really? It's what 
     we've got, it's what is tested.

 (b) Enforce that flags match. This may sound logical, but it will 
     actually *break* existing setups, because tons of drivers set 
     IRQF_DISABLED for no good reason (probably all totally historical)

 (c) "one IRQF_DISABLED means that everything runs disabled". This is 
     quite possibly buggy. There have been SCSI drivers with timeout 
     behaviour where they actually wait for timers to happen while in 
     their irq handlers. Bad form, and I *hope* we've fixed them all, but 
     I distinctly remember it being important that the timer had higher 
     priority than some SCSI drivers on some architecture.

 (d) "one !IRFQ_DISABLED means that everything runs with irq's on". I 
     don't think it's any better than the other behaviour.

 (e) Just ignore IRQF_DISABLED entirely when mixed with IRQF_SHARED, 
     because they're all pretty much guaranteed to be legacy and buggy and 
     pointless.

 (f) Disable and re-enable interrupts per handler.

Quite frankly, my preference would be (a) followed by (e) or (f), and 
(b)-(d) are in my opinion the worst of the lot with no upsides at all (and 
(b) in particular is pretty much _guaranteed_ to break existing setups).

			Linus

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

* Re: IRQF_DISABLED problem
  2007-07-26 23:04   ` Linus Torvalds
@ 2007-07-26 23:14     ` David Miller
  2007-07-26 23:17     ` Linus Torvalds
  1 sibling, 0 replies; 10+ messages in thread
From: David Miller @ 2007-07-26 23:14 UTC (permalink / raw)
  To: torvalds; +Cc: matthew, mingo, linux-kernel

From: Linus Torvalds <torvalds@linux-foundation.org>
Date: Thu, 26 Jul 2007 16:04:42 -0700 (PDT)

> Quite frankly, my preference would be (a) followed by (e) or (f), and 
> (b)-(d) are in my opinion the worst of the lot with no upsides at all (and 
> (b) in particular is pretty much _guaranteed_ to break existing setups).

I look at some cases, such as EHEA on powerpc which is a pretty
modern driver written by not clueless folks, and wonder if they
do it because they know the IRQ is non-shared, they know their
interrupt handler is insanely simple and short, and just want to
avoid the overhead of that sti()/cli() in the caller.

All the EHEA interrupt handler does is unconditionally set a state bit
and schedule a softirq, then return.

The powerpc folks do delayed IRQ enable/disable using software state,
but perhaps these drivers were written before that.

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

* Re: IRQF_DISABLED problem
  2007-07-26 23:04   ` Linus Torvalds
  2007-07-26 23:14     ` David Miller
@ 2007-07-26 23:17     ` Linus Torvalds
  2007-07-27 20:11       ` Arjan van de Ven
  1 sibling, 1 reply; 10+ messages in thread
From: Linus Torvalds @ 2007-07-26 23:17 UTC (permalink / raw)
  To: David Miller; +Cc: matthew, mingo, linux-kernel



On Thu, 26 Jul 2007, Linus Torvalds wrote:
> 
>  (c) "one IRQF_DISABLED means that everything runs disabled". This is 
>      quite possibly buggy.

(Side note: I'm not claiming this (or it's mirror image (d)) is really any 
better/worse than the current behaviour from a theoretical standpoint, but 
at least the current behaviour is _tested_, which makes it better in 
practice. So if we want to change this, I think we want to change it to 
something that is _obviously_ better).

		Linus

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

* Re: IRQF_DISABLED problem
  2007-07-26 23:17     ` Linus Torvalds
@ 2007-07-27 20:11       ` Arjan van de Ven
  2007-07-27 20:50         ` David Miller
  0 siblings, 1 reply; 10+ messages in thread
From: Arjan van de Ven @ 2007-07-27 20:11 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: David Miller, matthew, mingo, linux-kernel

On Thu, 2007-07-26 at 16:17 -0700, Linus Torvalds wrote:
> 
> On Thu, 26 Jul 2007, Linus Torvalds wrote:
> > 
> >  (c) "one IRQF_DISABLED means that everything runs disabled". This is 
> >      quite possibly buggy.
> 
> (Side note: I'm not claiming this (or it's mirror image (d)) is really any 
> better/worse than the current behaviour from a theoretical standpoint, but 
> at least the current behaviour is _tested_, which makes it better in 
> practice. So if we want to change this, I think we want to change it to 
> something that is _obviously_ better).

my personal preference would actually be to just never enable
interrupts. It's the fastest solution obviously, the most friendly on
stack and.. well simplest. Drivers no longer need to play some of the
games that they do today. And while there is an argument that this may
introduce a bit of latency... I'm not really convinced. The real work if
it's really heavy is supposed to happen in not-hard-irq context anyway,
and for all other cases interrupting the original handler is very likely
the most expensive thing in terms of adding latency to the system.


If I remember correctly there have been a few fedora releases which did
this, with no bad behavior.. I don't know if Fedora still does this.

-- 
if you want to mail me at work (you don't), use arjan (at) linux.intel.com
Test the interaction between Linux and your BIOS via http://www.linuxfirmwarekit.org


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

* Re: IRQF_DISABLED problem
  2007-07-27 20:11       ` Arjan van de Ven
@ 2007-07-27 20:50         ` David Miller
  0 siblings, 0 replies; 10+ messages in thread
From: David Miller @ 2007-07-27 20:50 UTC (permalink / raw)
  To: arjan; +Cc: torvalds, matthew, mingo, linux-kernel

From: Arjan van de Ven <arjan@infradead.org>
Date: Fri, 27 Jul 2007 13:11:56 -0700

> On Thu, 2007-07-26 at 16:17 -0700, Linus Torvalds wrote:
> > 
> > On Thu, 26 Jul 2007, Linus Torvalds wrote:
> > > 
> > >  (c) "one IRQF_DISABLED means that everything runs disabled". This is 
> > >      quite possibly buggy.
> > 
> > (Side note: I'm not claiming this (or it's mirror image (d)) is really any 
> > better/worse than the current behaviour from a theoretical standpoint, but 
> > at least the current behaviour is _tested_, which makes it better in 
> > practice. So if we want to change this, I think we want to change it to 
> > something that is _obviously_ better).
> 
> my personal preference would actually be to just never enable
> interrupts. It's the fastest solution obviously, the most friendly on
> stack and.. well simplest. Drivers no longer need to play some of the
> games that they do today. And while there is an argument that this may
> introduce a bit of latency... I'm not really convinced.

If you have a "chirpy" serial controller with only a 1 byte
fifo, even a quite reasonable interrupt handler can cause
receive characters to get lost if you disable interrupts during
the entirety of it's execution.

It really is needed.

And it's just plain rude to disable interrupts when it isn't
absolutely necessary.

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

* Re: IRQF_DISABLED problem
       [not found]     ` <fa./08N/HtpJQ6zg8Xc1K5pP6/aKMM@ifi.uio.no>
@ 2007-07-29 15:41       ` Robert Hancock
  2007-08-02 15:40         ` Mark Lord
  0 siblings, 1 reply; 10+ messages in thread
From: Robert Hancock @ 2007-07-29 15:41 UTC (permalink / raw)
  To: David Miller; +Cc: arjan, torvalds, matthew, mingo, linux-kernel

David Miller wrote:
> From: Arjan van de Ven <arjan@infradead.org>
> Date: Fri, 27 Jul 2007 13:11:56 -0700
> 
>> On Thu, 2007-07-26 at 16:17 -0700, Linus Torvalds wrote:
>>> On Thu, 26 Jul 2007, Linus Torvalds wrote:
>>>>  (c) "one IRQF_DISABLED means that everything runs disabled". This is 
>>>>      quite possibly buggy.
>>> (Side note: I'm not claiming this (or it's mirror image (d)) is really any 
>>> better/worse than the current behaviour from a theoretical standpoint, but 
>>> at least the current behaviour is _tested_, which makes it better in 
>>> practice. So if we want to change this, I think we want to change it to 
>>> something that is _obviously_ better).
>> my personal preference would actually be to just never enable
>> interrupts. It's the fastest solution obviously, the most friendly on
>> stack and.. well simplest. Drivers no longer need to play some of the
>> games that they do today. And while there is an argument that this may
>> introduce a bit of latency... I'm not really convinced.
> 
> If you have a "chirpy" serial controller with only a 1 byte
> fifo, even a quite reasonable interrupt handler can cause
> receive characters to get lost if you disable interrupts during
> the entirety of it's execution.
> 
> It really is needed.
> 
> And it's just plain rude to disable interrupts when it isn't
> absolutely necessary.

Does anyone really use those serial controllers with no FIFO anymore? 
They've never been reliable for remotely high speeds..

-- 
Robert Hancock      Saskatoon, SK, Canada
To email, remove "nospam" from hancockr@nospamshaw.ca
Home Page: http://www.roberthancock.com/


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

* Re: IRQF_DISABLED problem
  2007-07-29 15:41       ` IRQF_DISABLED problem Robert Hancock
@ 2007-08-02 15:40         ` Mark Lord
  0 siblings, 0 replies; 10+ messages in thread
From: Mark Lord @ 2007-08-02 15:40 UTC (permalink / raw)
  To: Robert Hancock
  Cc: David Miller, arjan, torvalds, matthew, mingo, linux-kernel

Robert Hancock wrote:
> David Miller wrote:
>> From: Arjan van de Ven <arjan@infradead.org>
>> Date: Fri, 27 Jul 2007 13:11:56 -0700
>>
>>> On Thu, 2007-07-26 at 16:17 -0700, Linus Torvalds wrote:
>>>> On Thu, 26 Jul 2007, Linus Torvalds wrote:
>>>>>  (c) "one IRQF_DISABLED means that everything runs disabled". This 
>>>>> is      quite possibly buggy.
>>>> (Side note: I'm not claiming this (or it's mirror image (d)) is 
>>>> really any better/worse than the current behaviour from a 
>>>> theoretical standpoint, but at least the current behaviour is 
>>>> _tested_, which makes it better in practice. So if we want to change 
>>>> this, I think we want to change it to something that is _obviously_ 
>>>> better).
>>> my personal preference would actually be to just never enable
>>> interrupts. It's the fastest solution obviously, the most friendly on
>>> stack and.. well simplest. Drivers no longer need to play some of the
>>> games that they do today. And while there is an argument that this may
>>> introduce a bit of latency... I'm not really convinced.
>>
>> If you have a "chirpy" serial controller with only a 1 byte
>> fifo, even a quite reasonable interrupt handler can cause
>> receive characters to get lost if you disable interrupts during
>> the entirety of it's execution.
>>
>> It really is needed.
>>
>> And it's just plain rude to disable interrupts when it isn't
>> absolutely necessary.
> 
> Does anyone really use those serial controllers with no FIFO anymore? 
> They've never been reliable for remotely high speeds..

There's another thread on lkml currently about this exact issue,
whereby the UART "fifo nearly full" interrupt isn't getting in quickly
enough for the kernel to de-assert RTS in time..

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

end of thread, other threads:[~2007-08-02 15:41 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <fa.mb8woD3e5JnT1x6AgEMOmnlVvg0@ifi.uio.no>
     [not found] ` <fa.axY2ukp7kqKVMAidyu4NVN81MbI@ifi.uio.no>
     [not found]   ` <fa.tS+LCGnYgeCNRIaF90yH21XBCqI@ifi.uio.no>
     [not found]     ` <fa./08N/HtpJQ6zg8Xc1K5pP6/aKMM@ifi.uio.no>
2007-07-29 15:41       ` IRQF_DISABLED problem Robert Hancock
2007-08-02 15:40         ` Mark Lord
2007-07-26 20:13 Matthew Wilcox
2007-07-26 20:41 ` Linus Torvalds
2007-07-26 22:23 ` David Miller
2007-07-26 23:04   ` Linus Torvalds
2007-07-26 23:14     ` David Miller
2007-07-26 23:17     ` Linus Torvalds
2007-07-27 20:11       ` Arjan van de Ven
2007-07-27 20:50         ` David Miller

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