2009-09-14 20:30:34

by Robert P. J. Day

[permalink] [raw]
Subject: test for "spurious" IRQ ignores possible IRQ_WAKE_THREAD value


never ashamed to embarrass myself in public, i just noticed the
following. from kernel/irq/spurious.c:

...
static void
__report_bad_irq(unsigned int irq, struct irq_desc *desc,
irqreturn_t action_ret)
{
struct irqaction *action;

if (action_ret != IRQ_HANDLED && action_ret != IRQ_NONE) {
printk(KERN_ERR "irq event %d: bogus return value %x\n",
irq, action_ret);

but from include/linux/irqreturn.h, we see *three* possible return
values:

enum irqreturn {
IRQ_NONE,
IRQ_HANDLED,
IRQ_WAKE_THREAD,
};

typedef enum irqreturn irqreturn_t;
#define IRQ_RETVAL(x) ((x) != IRQ_NONE)

is there an inconsistency here?

rday
--

========================================================================
Robert P. J. Day Waterloo, Ontario, CANADA

Linux Consulting, Training and Annoying Kernel Pedantry.

Web page: http://crashcourse.ca
Twitter: http://twitter.com/rpjday
========================================================================


2009-09-14 20:34:49

by Robert P. J. Day

[permalink] [raw]
Subject: Re: test for "spurious" IRQ ignores possible IRQ_WAKE_THREAD value

On Mon, 14 Sep 2009, Robert P. J. Day wrote:

> never ashamed to embarrass myself in public, i just noticed the
> following. from kernel/irq/spurious.c:
>
> ...
> static void
> __report_bad_irq(unsigned int irq, struct irq_desc *desc,
> irqreturn_t action_ret)
> {
> struct irqaction *action;
>
> if (action_ret != IRQ_HANDLED && action_ret != IRQ_NONE) {
> printk(KERN_ERR "irq event %d: bogus return value %x\n",
> irq, action_ret);
>
> but from include/linux/irqreturn.h, we see *three* possible return
> values:
>
> enum irqreturn {
> IRQ_NONE,
> IRQ_HANDLED,
> IRQ_WAKE_THREAD,
> };
>
> typedef enum irqreturn irqreturn_t;
> #define IRQ_RETVAL(x) ((x) != IRQ_NONE)
>
> is there an inconsistency here?

i should have pointed out that there is (apparently) only one place
in the entire tree that uses that third return value:

$ grep -rw IRQ_WAKE_THREAD *
drivers/net/wireless/b43/main.c: return IRQ_WAKE_THREAD; <-- there
include/linux/irqreturn.h: * @IRQ_WAKE_THREAD handler requests to wake the handler thread
include/linux/irqreturn.h: IRQ_WAKE_THREAD,
Binary file include/linux/.irqreturn.h.swp matches
include/linux/interrupt.h: * IRQTF_WARNED - warning "IRQ_WAKE_THREAD w/o thread_fn" has been printed
kernel/irq/handle.c: printk(KERN_WARNING "IRQ %d device %s returned IRQ_WAKE_THREAD "
kernel/irq/handle.c: case IRQ_WAKE_THREAD:
kernel/irq/manage.c: return IRQ_WAKE_THREAD;
kernel/irq/manage.c: * IRQ_WAKE_THREAD which will wake up the handler thread and run
$

for what that's worth.

rday
--

========================================================================
Robert P. J. Day Waterloo, Ontario, CANADA

Linux Consulting, Training and Annoying Kernel Pedantry.

Web page: http://crashcourse.ca
Twitter: http://twitter.com/rpjday
========================================================================

2009-09-17 19:34:17

by Cyrill Gorcunov

[permalink] [raw]
Subject: Re: test for "spurious" IRQ ignores possible IRQ_WAKE_THREAD value

[Robert P. J. Day - Mon, Sep 14, 2009 at 04:34:48PM -0400]
| On Mon, 14 Sep 2009, Robert P. J. Day wrote:
|
| > never ashamed to embarrass myself in public, i just noticed the
| > following. from kernel/irq/spurious.c:
| >
| > ...
| > static void
| > __report_bad_irq(unsigned int irq, struct irq_desc *desc,
| > irqreturn_t action_ret)
| > {
| > struct irqaction *action;
| >
| > if (action_ret != IRQ_HANDLED && action_ret != IRQ_NONE) {
| > printk(KERN_ERR "irq event %d: bogus return value %x\n",
| > irq, action_ret);
| >
| > but from include/linux/irqreturn.h, we see *three* possible return
| > values:
| >
| > enum irqreturn {
| > IRQ_NONE,
| > IRQ_HANDLED,
| > IRQ_WAKE_THREAD,
| > };
| >
| > typedef enum irqreturn irqreturn_t;
| > #define IRQ_RETVAL(x) ((x) != IRQ_NONE)
| >
| > is there an inconsistency here?
|
...

Hi Robert,

It could that IRQ_WAKE_THREAD is just missed here. I suppose it
was brough there as thread irq merged. But I think only Thomas
know for sure, I definitely miss something :) CC'ed

-- Cyrill

2009-09-17 19:52:39

by Thomas Gleixner

[permalink] [raw]
Subject: Re: test for "spurious" IRQ ignores possible IRQ_WAKE_THREAD value

On Thu, 17 Sep 2009, Cyrill Gorcunov wrote:
> [Robert P. J. Day - Mon, Sep 14, 2009 at 04:34:48PM -0400]
> | On Mon, 14 Sep 2009, Robert P. J. Day wrote:
> |
> | > never ashamed to embarrass myself in public, i just noticed the
> | > following. from kernel/irq/spurious.c:
> | >
> | > ...
> | > static void
> | > __report_bad_irq(unsigned int irq, struct irq_desc *desc,
> | > irqreturn_t action_ret)
> | > {
> | > struct irqaction *action;
> | >
> | > if (action_ret != IRQ_HANDLED && action_ret != IRQ_NONE) {
> | > printk(KERN_ERR "irq event %d: bogus return value %x\n",
> | > irq, action_ret);
> | >
> | > but from include/linux/irqreturn.h, we see *three* possible return
> | > values:
> | >
> | > enum irqreturn {
> | > IRQ_NONE,
> | > IRQ_HANDLED,
> | > IRQ_WAKE_THREAD,
> | > };
> | >
> | > typedef enum irqreturn irqreturn_t;
> | > #define IRQ_RETVAL(x) ((x) != IRQ_NONE)
> | >
> | > is there an inconsistency here?
> |
> ...
>
> Hi Robert,
>
> It could that IRQ_WAKE_THREAD is just missed here. I suppose it
> was brough there as thread irq merged. But I think only Thomas
> know for sure, I definitely miss something :) CC'ed

from kernel/irq/handle.c:

trace_irq_handler_entry(irq, action);
ret = action->handler(irq, action->dev_id);
trace_irq_handler_exit(irq, action, ret);

switch (ret) {
case IRQ_WAKE_THREAD:
/*
* Set result to handled so the spurious check
* does not trigger.
*/
ret = IRQ_HANDLED;

So nothing to worry about :)

Thanks,

tglx

2009-09-17 20:08:37

by Robert P. J. Day

[permalink] [raw]
Subject: Re: test for "spurious" IRQ ignores possible IRQ_WAKE_THREAD value

On Thu, 17 Sep 2009, Cyrill Gorcunov wrote:

> [Robert P. J. Day - Mon, Sep 14, 2009 at 04:34:48PM -0400]
> | On Mon, 14 Sep 2009, Robert P. J. Day wrote:
> |
> | > never ashamed to embarrass myself in public, i just noticed the
> | > following. from kernel/irq/spurious.c:
> | >
> | > ...
> | > static void
> | > __report_bad_irq(unsigned int irq, struct irq_desc *desc,
> | > irqreturn_t action_ret)
> | > {
> | > struct irqaction *action;
> | >
> | > if (action_ret != IRQ_HANDLED && action_ret != IRQ_NONE) {
> | > printk(KERN_ERR "irq event %d: bogus return value %x\n",
> | > irq, action_ret);
> | >
> | > but from include/linux/irqreturn.h, we see *three* possible return
> | > values:
> | >
> | > enum irqreturn {
> | > IRQ_NONE,
> | > IRQ_HANDLED,
> | > IRQ_WAKE_THREAD,
> | > };
> | >
> | > typedef enum irqreturn irqreturn_t;
> | > #define IRQ_RETVAL(x) ((x) != IRQ_NONE)
> | >
> | > is there an inconsistency here?
> |
> ...
>
> Hi Robert,
>
> It could that IRQ_WAKE_THREAD is just missed here. I suppose it was
> brough there as thread irq merged. But I think only Thomas know for
> sure, I definitely miss something :) CC'ed

actually, after a bit more reading, i found this in
kernel/irq/handle.c:
...
switch (ret) {
case IRQ_WAKE_THREAD:
/*
* Set result to handled so the spurious check
* does not trigger.
*/
ret = IRQ_HANDLED;
...

so it looks like that value of IRQ_WAKE_THREAD is simply "mapped" to
IRQ_HANDLED, and perhaps that's done before __report_bad_irq is ever
called so that that latter routine never sees a value of
IRQ_WAKE_THREAD. but that's just a guess.

rday
--


========================================================================
Robert P. J. Day Waterloo, Ontario, CANADA

Linux Consulting, Training and Annoying Kernel Pedantry.

Web page: http://crashcourse.ca
Twitter: http://twitter.com/rpjday
========================================================================

2009-09-17 20:18:13

by Cyrill Gorcunov

[permalink] [raw]
Subject: Re: test for "spurious" IRQ ignores possible IRQ_WAKE_THREAD value

[Robert P. J. Day - Thu, Sep 17, 2009 at 04:08:32PM -0400]
...
| > Hi Robert,
| >
| > It could that IRQ_WAKE_THREAD is just missed here. I suppose it was
| > brough there as thread irq merged. But I think only Thomas know for
| > sure, I definitely miss something :) CC'ed
|
| actually, after a bit more reading, i found this in
| kernel/irq/handle.c:
| ...
| switch (ret) {
| case IRQ_WAKE_THREAD:
| /*
| * Set result to handled so the spurious check
| * does not trigger.
| */
| ret = IRQ_HANDLED;
| ...
|
| so it looks like that value of IRQ_WAKE_THREAD is simply "mapped" to
| IRQ_HANDLED, and perhaps that's done before __report_bad_irq is ever
| called so that that latter routine never sees a value of
| IRQ_WAKE_THREAD. but that's just a guess.
|
| rday
| --

yeah, Thomas just pointed it too :) The note_interrupt is
called after handle_IRQ_event (except a few drivers which
don;t use threaded irq) so it doesnt reach bad irq state
with IRQ_WAKE_THREAD, for now at least.

-- Cyrill