* [PATCH 1/3] irq/spurious: dump also the name of the threaded handler @ 2011-05-31 6:56 Sebastian Andrzej Siewior 2011-05-31 6:56 ` [PATCH 2/3] irq: handle spurios irq detection for threaded irqs Sebastian Andrzej Siewior ` (2 more replies) 0 siblings, 3 replies; 9+ messages in thread From: Sebastian Andrzej Siewior @ 2011-05-31 6:56 UTC (permalink / raw) To: Thomas Gleixner; +Cc: linux-kernel, Sebastian Andrzej Siewior In forced threaded mode (or with explicit threaded handler) we only see the primary handler, not the actual threaded handler which does not feel to be responsible. Signed-off-by: Sebastian Andrzej Siewior <sebastian@breakpoint.cc> --- kernel/irq/spurious.c | 9 +++++---- 1 files changed, 5 insertions(+), 4 deletions(-) diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c index dfbd550..c9a78ba 100644 --- a/kernel/irq/spurious.c +++ b/kernel/irq/spurious.c @@ -201,10 +201,11 @@ __report_bad_irq(unsigned int irq, struct irq_desc *desc, raw_spin_lock_irqsave(&desc->lock, flags); action = desc->action; while (action) { - printk(KERN_ERR "[<%p>]", action->handler); - print_symbol(" (%s)", - (unsigned long)action->handler); - printk("\n"); + printk(KERN_ERR "[<%p>] %pf", action->handler, action->handler); + if (action->thread_fn) + printk(KERN_CONT " threaded [<%p>] %pf", + action->thread_fn, action->thread_fn); + printk(KERN_CONT "\n"); action = action->next; } raw_spin_unlock_irqrestore(&desc->lock, flags); -- 1.7.4.4 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/3] irq: handle spurios irq detection for threaded irqs 2011-05-31 6:56 [PATCH 1/3] irq/spurious: dump also the name of the threaded handler Sebastian Andrzej Siewior @ 2011-05-31 6:56 ` Sebastian Andrzej Siewior 2011-05-31 10:35 ` Thomas Gleixner 2011-06-03 12:58 ` [tip:irq/urgent] irq: Handle " tip-bot for Sebastian Andrzej Siewior 2011-05-31 6:56 ` [PATCH 3/3] irq: catch more wrong return values from interrupt handlers Sebastian Andrzej Siewior 2011-06-03 12:57 ` [tip:irq/urgent] genirq: Print threaded handler in spurious debug output tip-bot for Sebastian Andrzej Siewior 2 siblings, 2 replies; 9+ messages in thread From: Sebastian Andrzej Siewior @ 2011-05-31 6:56 UTC (permalink / raw) To: Thomas Gleixner; +Cc: linux-kernel, Sebastian Andrzej Siewior The detection of spurios interrupts is currently limited to first level handler. In force-threaded mode we never notice if the threaded irq does not feel responsible. This patch catches the return value of the threaded handler and forwards it to the spurious detector. If the primary handler returns only IRQ_WAKE_THREAD then the spourious detector ignores it because it gets called again from the threaded handler. Signed-off-by: Sebastian Andrzej Siewior <sebastian@breakpoint.cc> --- include/linux/irqreturn.h | 6 +++--- kernel/irq/handle.c | 6 ------ kernel/irq/manage.c | 27 +++++++++++++++++++++------ kernel/irq/spurious.c | 19 +++++++++++++++---- 4 files changed, 39 insertions(+), 19 deletions(-) diff --git a/include/linux/irqreturn.h b/include/linux/irqreturn.h index 819acaa..714ba08 100644 --- a/include/linux/irqreturn.h +++ b/include/linux/irqreturn.h @@ -8,9 +8,9 @@ * @IRQ_WAKE_THREAD handler requests to wake the handler thread */ enum irqreturn { - IRQ_NONE, - IRQ_HANDLED, - IRQ_WAKE_THREAD, + IRQ_NONE = (0 << 0), + IRQ_HANDLED = (1 << 0), + IRQ_WAKE_THREAD = (1 << 1), }; typedef enum irqreturn irqreturn_t; diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index 90cb55f..470d08c 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c @@ -133,12 +133,6 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action) switch (res) { case IRQ_WAKE_THREAD: /* - * Set result to handled so the spurious check - * does not trigger. - */ - res = IRQ_HANDLED; - - /* * Catch drivers which return WAKE_THREAD but * did not set up a thread function */ diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index f7ce002..f4d5329 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -723,13 +723,16 @@ irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action) { } * context. So we need to disable bh here to avoid deadlocks and other * side effects. */ -static void +static irqreturn_t irq_forced_thread_fn(struct irq_desc *desc, struct irqaction *action) { + irqreturn_t ret; + local_bh_disable(); - action->thread_fn(action->irq, action->dev_id); + ret = action->thread_fn(action->irq, action->dev_id); irq_finalize_oneshot(desc, action, false); local_bh_enable(); + return ret; } /* @@ -737,10 +740,14 @@ irq_forced_thread_fn(struct irq_desc *desc, struct irqaction *action) * preemtible - many of them need to sleep and wait for slow busses to * complete. */ -static void irq_thread_fn(struct irq_desc *desc, struct irqaction *action) +static irqreturn_t irq_thread_fn(struct irq_desc *desc, + struct irqaction *action) { - action->thread_fn(action->irq, action->dev_id); + irqreturn_t ret; + + ret = action->thread_fn(action->irq, action->dev_id); irq_finalize_oneshot(desc, action, false); + return ret; } /* @@ -753,7 +760,8 @@ static int irq_thread(void *data) }; struct irqaction *action = data; struct irq_desc *desc = irq_to_desc(action->irq); - void (*handler_fn)(struct irq_desc *desc, struct irqaction *action); + irqreturn_t (*handler_fn)(struct irq_desc *desc, + struct irqaction *action); int wake; if (force_irqthreads & test_bit(IRQTF_FORCED_THREAD, @@ -783,8 +791,15 @@ static int irq_thread(void *data) desc->istate |= IRQS_PENDING; raw_spin_unlock_irq(&desc->lock); } else { + irqreturn_t action_ret; + raw_spin_unlock_irq(&desc->lock); - handler_fn(desc, action); + action_ret = handler_fn(desc, action); + if (!noirqdebug) { + raw_spin_lock_irq(&desc->lock); + note_interrupt(action->irq, desc, action_ret); + raw_spin_unlock_irq(&desc->lock); + } } wake = atomic_dec_and_test(&desc->threads_active); diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c index c9a78ba..0992587 100644 --- a/kernel/irq/spurious.c +++ b/kernel/irq/spurious.c @@ -167,6 +167,13 @@ out: jiffies + POLL_SPURIOUS_IRQ_INTERVAL); } +static int bad_action_ret(irqreturn_t action_ret) +{ + if (likely(action_ret <= (IRQ_HANDLED | IRQ_WAKE_THREAD))) + return 0; + return 1; +} + /* * If 99,900 of the previous 100,000 interrupts have not been handled * then assume that the IRQ is stuck in some manner. Drop a diagnostic @@ -182,7 +189,7 @@ __report_bad_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *action; unsigned long flags; - if (action_ret != IRQ_HANDLED && action_ret != IRQ_NONE) { + if (bad_action_ret(action_ret)) { printk(KERN_ERR "irq event %d: bogus return value %x\n", irq, action_ret); } else { @@ -263,7 +270,11 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc, if (desc->istate & IRQS_POLL_INPROGRESS) return; - if (unlikely(action_ret != IRQ_HANDLED)) { + /* we get here again via the threaded handler */ + if (action_ret == IRQ_WAKE_THREAD) + return; + + if (unlikely(action_ret == IRQ_NONE)) { /* * If we are seeing only the odd spurious IRQ caused by * bus asynchronicity then don't eventually trigger an error, @@ -275,9 +286,9 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc, else desc->irqs_unhandled++; desc->last_unhandled = jiffies; - if (unlikely(action_ret != IRQ_NONE)) - report_bad_irq(irq, desc, action_ret); } + if (bad_action_ret(action_ret)) + report_bad_irq(irq, desc, action_ret); if (unlikely(try_misrouted_irq(irq, desc, action_ret))) { int ok = misrouted_irq(irq); -- 1.7.4.4 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 2/3] irq: handle spurios irq detection for threaded irqs 2011-05-31 6:56 ` [PATCH 2/3] irq: handle spurios irq detection for threaded irqs Sebastian Andrzej Siewior @ 2011-05-31 10:35 ` Thomas Gleixner 2011-06-01 6:33 ` [PATCH v2] " Sebastian Andrzej Siewior 2011-06-03 12:58 ` [tip:irq/urgent] irq: Handle " tip-bot for Sebastian Andrzej Siewior 1 sibling, 1 reply; 9+ messages in thread From: Thomas Gleixner @ 2011-05-31 10:35 UTC (permalink / raw) To: Sebastian Andrzej Siewior; +Cc: linux-kernel On Tue, 31 May 2011, Sebastian Andrzej Siewior wrote: > raw_spin_unlock_irq(&desc->lock); > - handler_fn(desc, action); > + action_ret = handler_fn(desc, action); > + if (!noirqdebug) { > + raw_spin_lock_irq(&desc->lock); Hmm. This will deadlock in __report_bad_irq(). > + note_interrupt(action->irq, desc, action_ret); > + raw_spin_unlock_irq(&desc->lock); > + } Thanks, tglx ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2] irq: handle spurios irq detection for threaded irqs 2011-05-31 10:35 ` Thomas Gleixner @ 2011-06-01 6:33 ` Sebastian Andrzej Siewior 0 siblings, 0 replies; 9+ messages in thread From: Sebastian Andrzej Siewior @ 2011-06-01 6:33 UTC (permalink / raw) To: Thomas Gleixner; +Cc: linux-kernel The detection of spurios interrupts is currently limited to first level handlers. So in force-threaded mode we never notice if the threaded irq does not feel responsible. This patch catches the return value and forwards it to the spurious detector. If the primary handler returns only IRQ_WAKE_THREAD then the spourious detector ignores it because it gets called again from the threaded handler. Signed-off-by: Sebastian Andrzej Siewior <sebastian@breakpoint.cc> --- include/linux/irqreturn.h | 6 +++--- kernel/irq/handle.c | 6 ------ kernel/irq/manage.c | 24 ++++++++++++++++++------ kernel/irq/spurious.c | 19 +++++++++++++++---- 4 files changed, 36 insertions(+), 19 deletions(-) diff --git a/include/linux/irqreturn.h b/include/linux/irqreturn.h index 819acaa..714ba08 100644 --- a/include/linux/irqreturn.h +++ b/include/linux/irqreturn.h @@ -8,9 +8,9 @@ * @IRQ_WAKE_THREAD handler requests to wake the handler thread */ enum irqreturn { - IRQ_NONE, - IRQ_HANDLED, - IRQ_WAKE_THREAD, + IRQ_NONE = (0 << 0), + IRQ_HANDLED = (1 << 0), + IRQ_WAKE_THREAD = (1 << 1), }; typedef enum irqreturn irqreturn_t; diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index 90cb55f..470d08c 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c @@ -133,12 +133,6 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action) switch (res) { case IRQ_WAKE_THREAD: /* - * Set result to handled so the spurious check - * does not trigger. - */ - res = IRQ_HANDLED; - - /* * Catch drivers which return WAKE_THREAD but * did not set up a thread function */ diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index f7ce002..d64bafb 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -723,13 +723,16 @@ irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action) { } * context. So we need to disable bh here to avoid deadlocks and other * side effects. */ -static void +static irqreturn_t irq_forced_thread_fn(struct irq_desc *desc, struct irqaction *action) { + irqreturn_t ret; + local_bh_disable(); - action->thread_fn(action->irq, action->dev_id); + ret = action->thread_fn(action->irq, action->dev_id); irq_finalize_oneshot(desc, action, false); local_bh_enable(); + return ret; } /* @@ -737,10 +740,14 @@ irq_forced_thread_fn(struct irq_desc *desc, struct irqaction *action) * preemtible - many of them need to sleep and wait for slow busses to * complete. */ -static void irq_thread_fn(struct irq_desc *desc, struct irqaction *action) +static irqreturn_t irq_thread_fn(struct irq_desc *desc, + struct irqaction *action) { - action->thread_fn(action->irq, action->dev_id); + irqreturn_t ret; + + ret = action->thread_fn(action->irq, action->dev_id); irq_finalize_oneshot(desc, action, false); + return ret; } /* @@ -753,7 +760,8 @@ static int irq_thread(void *data) }; struct irqaction *action = data; struct irq_desc *desc = irq_to_desc(action->irq); - void (*handler_fn)(struct irq_desc *desc, struct irqaction *action); + irqreturn_t (*handler_fn)(struct irq_desc *desc, + struct irqaction *action); int wake; if (force_irqthreads & test_bit(IRQTF_FORCED_THREAD, @@ -783,8 +791,12 @@ static int irq_thread(void *data) desc->istate |= IRQS_PENDING; raw_spin_unlock_irq(&desc->lock); } else { + irqreturn_t action_ret; + raw_spin_unlock_irq(&desc->lock); - handler_fn(desc, action); + action_ret = handler_fn(desc, action); + if (!noirqdebug) + note_interrupt(action->irq, desc, action_ret); } wake = atomic_dec_and_test(&desc->threads_active); diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c index c9a78ba..0992587 100644 --- a/kernel/irq/spurious.c +++ b/kernel/irq/spurious.c @@ -167,6 +167,13 @@ out: jiffies + POLL_SPURIOUS_IRQ_INTERVAL); } +static int bad_action_ret(irqreturn_t action_ret) +{ + if (likely(action_ret <= (IRQ_HANDLED | IRQ_WAKE_THREAD))) + return 0; + return 1; +} + /* * If 99,900 of the previous 100,000 interrupts have not been handled * then assume that the IRQ is stuck in some manner. Drop a diagnostic @@ -182,7 +189,7 @@ __report_bad_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *action; unsigned long flags; - if (action_ret != IRQ_HANDLED && action_ret != IRQ_NONE) { + if (bad_action_ret(action_ret)) { printk(KERN_ERR "irq event %d: bogus return value %x\n", irq, action_ret); } else { @@ -263,7 +270,11 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc, if (desc->istate & IRQS_POLL_INPROGRESS) return; - if (unlikely(action_ret != IRQ_HANDLED)) { + /* we get here again via the threaded handler */ + if (action_ret == IRQ_WAKE_THREAD) + return; + + if (unlikely(action_ret == IRQ_NONE)) { /* * If we are seeing only the odd spurious IRQ caused by * bus asynchronicity then don't eventually trigger an error, @@ -275,9 +286,9 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc, else desc->irqs_unhandled++; desc->last_unhandled = jiffies; - if (unlikely(action_ret != IRQ_NONE)) - report_bad_irq(irq, desc, action_ret); } + if (bad_action_ret(action_ret)) + report_bad_irq(irq, desc, action_ret); if (unlikely(try_misrouted_irq(irq, desc, action_ret))) { int ok = misrouted_irq(irq); -- 1.7.4.4 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [tip:irq/urgent] irq: Handle spurios irq detection for threaded irqs 2011-05-31 6:56 ` [PATCH 2/3] irq: handle spurios irq detection for threaded irqs Sebastian Andrzej Siewior 2011-05-31 10:35 ` Thomas Gleixner @ 2011-06-03 12:58 ` tip-bot for Sebastian Andrzej Siewior 1 sibling, 0 replies; 9+ messages in thread From: tip-bot for Sebastian Andrzej Siewior @ 2011-06-03 12:58 UTC (permalink / raw) To: linux-tip-commits; +Cc: linux-kernel, hpa, mingo, sebastian, tglx Commit-ID: 3a43e05f4d0600e906fa09f4a65d749288c44592 Gitweb: http://git.kernel.org/tip/3a43e05f4d0600e906fa09f4a65d749288c44592 Author: Sebastian Andrzej Siewior <sebastian@breakpoint.cc> AuthorDate: Tue, 31 May 2011 08:56:11 +0200 Committer: Thomas Gleixner <tglx@linutronix.de> CommitDate: Fri, 3 Jun 2011 14:53:15 +0200 irq: Handle spurios irq detection for threaded irqs The detection of spurios interrupts is currently limited to first level handler. In force-threaded mode we never notice if the threaded irq does not feel responsible. This patch catches the return value of the threaded handler and forwards it to the spurious detector. If the primary handler returns only IRQ_WAKE_THREAD then the spourious detector ignores it because it gets called again from the threaded handler. [ tglx: Report the erroneous return value early and bail out ] Signed-off-by: Sebastian Andrzej Siewior <sebastian@breakpoint.cc> Link: http://lkml.kernel.org/r/1306824972-27067-2-git-send-email-sebastian@breakpoint.cc Signed-off-by: Thomas Gleixner <tglx@linutronix.de> --- include/linux/irqreturn.h | 6 +++--- kernel/irq/handle.c | 6 ------ kernel/irq/manage.c | 24 ++++++++++++++++++------ kernel/irq/spurious.c | 22 ++++++++++++++++++---- 4 files changed, 39 insertions(+), 19 deletions(-) diff --git a/include/linux/irqreturn.h b/include/linux/irqreturn.h index 819acaa..714ba08 100644 --- a/include/linux/irqreturn.h +++ b/include/linux/irqreturn.h @@ -8,9 +8,9 @@ * @IRQ_WAKE_THREAD handler requests to wake the handler thread */ enum irqreturn { - IRQ_NONE, - IRQ_HANDLED, - IRQ_WAKE_THREAD, + IRQ_NONE = (0 << 0), + IRQ_HANDLED = (1 << 0), + IRQ_WAKE_THREAD = (1 << 1), }; typedef enum irqreturn irqreturn_t; diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index 90cb55f..470d08c 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c @@ -133,12 +133,6 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action) switch (res) { case IRQ_WAKE_THREAD: /* - * Set result to handled so the spurious check - * does not trigger. - */ - res = IRQ_HANDLED; - - /* * Catch drivers which return WAKE_THREAD but * did not set up a thread function */ diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index f7ce002..d64bafb 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -723,13 +723,16 @@ irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action) { } * context. So we need to disable bh here to avoid deadlocks and other * side effects. */ -static void +static irqreturn_t irq_forced_thread_fn(struct irq_desc *desc, struct irqaction *action) { + irqreturn_t ret; + local_bh_disable(); - action->thread_fn(action->irq, action->dev_id); + ret = action->thread_fn(action->irq, action->dev_id); irq_finalize_oneshot(desc, action, false); local_bh_enable(); + return ret; } /* @@ -737,10 +740,14 @@ irq_forced_thread_fn(struct irq_desc *desc, struct irqaction *action) * preemtible - many of them need to sleep and wait for slow busses to * complete. */ -static void irq_thread_fn(struct irq_desc *desc, struct irqaction *action) +static irqreturn_t irq_thread_fn(struct irq_desc *desc, + struct irqaction *action) { - action->thread_fn(action->irq, action->dev_id); + irqreturn_t ret; + + ret = action->thread_fn(action->irq, action->dev_id); irq_finalize_oneshot(desc, action, false); + return ret; } /* @@ -753,7 +760,8 @@ static int irq_thread(void *data) }; struct irqaction *action = data; struct irq_desc *desc = irq_to_desc(action->irq); - void (*handler_fn)(struct irq_desc *desc, struct irqaction *action); + irqreturn_t (*handler_fn)(struct irq_desc *desc, + struct irqaction *action); int wake; if (force_irqthreads & test_bit(IRQTF_FORCED_THREAD, @@ -783,8 +791,12 @@ static int irq_thread(void *data) desc->istate |= IRQS_PENDING; raw_spin_unlock_irq(&desc->lock); } else { + irqreturn_t action_ret; + raw_spin_unlock_irq(&desc->lock); - handler_fn(desc, action); + action_ret = handler_fn(desc, action); + if (!noirqdebug) + note_interrupt(action->irq, desc, action_ret); } wake = atomic_dec_and_test(&desc->threads_active); diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c index c9a78ba..aa57d5d 100644 --- a/kernel/irq/spurious.c +++ b/kernel/irq/spurious.c @@ -167,6 +167,13 @@ out: jiffies + POLL_SPURIOUS_IRQ_INTERVAL); } +static inline int bad_action_ret(irqreturn_t action_ret) +{ + if (likely(action_ret <= (IRQ_HANDLED | IRQ_WAKE_THREAD))) + return 0; + return 1; +} + /* * If 99,900 of the previous 100,000 interrupts have not been handled * then assume that the IRQ is stuck in some manner. Drop a diagnostic @@ -182,7 +189,7 @@ __report_bad_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *action; unsigned long flags; - if (action_ret != IRQ_HANDLED && action_ret != IRQ_NONE) { + if (bad_action_ret(action_ret)) { printk(KERN_ERR "irq event %d: bogus return value %x\n", irq, action_ret); } else { @@ -263,7 +270,16 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc, if (desc->istate & IRQS_POLL_INPROGRESS) return; - if (unlikely(action_ret != IRQ_HANDLED)) { + /* we get here again via the threaded handler */ + if (action_ret == IRQ_WAKE_THREAD) + return; + + if (bad_action_ret(action_ret)) { + report_bad_irq(irq, desc, action_ret); + return; + } + + if (unlikely(action_ret == IRQ_NONE)) { /* * If we are seeing only the odd spurious IRQ caused by * bus asynchronicity then don't eventually trigger an error, @@ -275,8 +291,6 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc, else desc->irqs_unhandled++; desc->last_unhandled = jiffies; - if (unlikely(action_ret != IRQ_NONE)) - report_bad_irq(irq, desc, action_ret); } if (unlikely(try_misrouted_irq(irq, desc, action_ret))) { ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 3/3] irq: catch more wrong return values from interrupt handlers 2011-05-31 6:56 [PATCH 1/3] irq/spurious: dump also the name of the threaded handler Sebastian Andrzej Siewior 2011-05-31 6:56 ` [PATCH 2/3] irq: handle spurios irq detection for threaded irqs Sebastian Andrzej Siewior @ 2011-05-31 6:56 ` Sebastian Andrzej Siewior 2011-05-31 10:32 ` Thomas Gleixner 2011-06-03 12:57 ` [tip:irq/urgent] genirq: Print threaded handler in spurious debug output tip-bot for Sebastian Andrzej Siewior 2 siblings, 1 reply; 9+ messages in thread From: Sebastian Andrzej Siewior @ 2011-05-31 6:56 UTC (permalink / raw) To: Thomas Gleixner; +Cc: linux-kernel, Sebastian Andrzej Siewior We now also accept return value IRQ_WAKE_THREAD from a threaded interrupt or IRQ_HANDLED | IRQ_WAKE_THREAD from primary and theaded handler which is wrong. We need to accept the later on shared handlers where one handler is primary only and the second is a threaded handler. This patch attempts to catch them. Unfortunately this patch introduces two new types so I'm not sure if it is worth it. Signed-off-by: Sebastian Andrzej Siewior <sebastian@breakpoint.cc> --- include/linux/irqreturn.h | 4 ++++ kernel/irq/chip.c | 5 ++++- kernel/irq/handle.c | 4 ++++ kernel/irq/manage.c | 2 ++ kernel/irq/spurious.c | 2 +- 5 files changed, 15 insertions(+), 2 deletions(-) diff --git a/include/linux/irqreturn.h b/include/linux/irqreturn.h index 714ba08..2374005 100644 --- a/include/linux/irqreturn.h +++ b/include/linux/irqreturn.h @@ -6,11 +6,15 @@ * @IRQ_NONE interrupt was not from this device * @IRQ_HANDLED interrupt was handled by this device * @IRQ_WAKE_THREAD handler requests to wake the handler thread + * @IRQ_HANDLED_WAKE interal type, don't use it + * @IRQ_WRONG_TYPE interal type, don't use it */ enum irqreturn { IRQ_NONE = (0 << 0), IRQ_HANDLED = (1 << 0), IRQ_WAKE_THREAD = (1 << 1), + IRQ_HANDLED_WAKE = (IRQ_HANDLED | IRQ_WAKE_THREAD), + IRQ_WRONG_RET = (1 << 2), }; typedef enum irqreturn irqreturn_t; diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index d5a3009..c4494b3 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -260,8 +260,11 @@ void handle_nested_irq(unsigned int irq) raw_spin_unlock_irq(&desc->lock); action_ret = action->thread_fn(action->irq, action->dev_id); - if (!noirqdebug) + if (!noirqdebug) { + if (action_ret > IRQ_HANDLED) + action_ret |= IRQ_WRONG_RET; note_interrupt(irq, desc, action_ret); + } raw_spin_lock_irq(&desc->lock); irqd_clear(&desc->irq_data, IRQD_IRQ_INPROGRESS); diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index 470d08c..15b070b 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c @@ -148,6 +148,10 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action) random |= action->flags; break; + case IRQ_HANDLED_WAKE: + res = IRQ_WRONG_RET; + break; + default: break; } diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index f4d5329..0a50547 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -796,6 +796,8 @@ static int irq_thread(void *data) raw_spin_unlock_irq(&desc->lock); action_ret = handler_fn(desc, action); if (!noirqdebug) { + if (action_ret > IRQ_HANDLED) + action_ret |= IRQ_WRONG_RET; raw_spin_lock_irq(&desc->lock); note_interrupt(action->irq, desc, action_ret); raw_spin_unlock_irq(&desc->lock); diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c index 0992587..2da50e6 100644 --- a/kernel/irq/spurious.c +++ b/kernel/irq/spurious.c @@ -169,7 +169,7 @@ out: static int bad_action_ret(irqreturn_t action_ret) { - if (likely(action_ret <= (IRQ_HANDLED | IRQ_WAKE_THREAD))) + if (likely(action_ret <= IRQ_HANDLED_WAKE)) return 0; return 1; } -- 1.7.4.4 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 3/3] irq: catch more wrong return values from interrupt handlers 2011-05-31 6:56 ` [PATCH 3/3] irq: catch more wrong return values from interrupt handlers Sebastian Andrzej Siewior @ 2011-05-31 10:32 ` Thomas Gleixner 2011-05-31 12:59 ` Sebastian Andrzej Siewior 0 siblings, 1 reply; 9+ messages in thread From: Thomas Gleixner @ 2011-05-31 10:32 UTC (permalink / raw) To: Sebastian Andrzej Siewior; +Cc: linux-kernel On Tue, 31 May 2011, Sebastian Andrzej Siewior wrote: > We now also accept return value IRQ_WAKE_THREAD from a threaded > interrupt or IRQ_HANDLED | IRQ_WAKE_THREAD from primary and theaded > handler which is wrong. We need to accept the later on shared handlers > where one handler is primary only and the second is a threaded handler. > This patch attempts to catch them. Unfortunately this patch introduces > two new types so I'm not sure if it is worth it. I'd rather avoid that ugliness. If driver writers are that stupid, there is probably more significant wreckage than this. Thanks, tglx ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 3/3] irq: catch more wrong return values from interrupt handlers 2011-05-31 10:32 ` Thomas Gleixner @ 2011-05-31 12:59 ` Sebastian Andrzej Siewior 0 siblings, 0 replies; 9+ messages in thread From: Sebastian Andrzej Siewior @ 2011-05-31 12:59 UTC (permalink / raw) To: Thomas Gleixner; +Cc: linux-kernel * Thomas Gleixner | 2011-05-31 12:32:58 [+0200]: >On Tue, 31 May 2011, Sebastian Andrzej Siewior wrote: > >> We now also accept return value IRQ_WAKE_THREAD from a threaded >> interrupt or IRQ_HANDLED | IRQ_WAKE_THREAD from primary and theaded >> handler which is wrong. We need to accept the later on shared handlers >> where one handler is primary only and the second is a threaded handler. >> This patch attempts to catch them. Unfortunately this patch introduces >> two new types so I'm not sure if it is worth it. > >I'd rather avoid that ugliness. If driver writers are that stupid, >there is probably more significant wreckage than this. Sure. It is just that the "old" code ensured that either NONE or HANDLED is returned and nothing else and the previous patch broke that check. This patch just points it out :) Do you want bad_action_ret() removed or kept as it? >Thanks, > > tglx Sebastian ^ permalink raw reply [flat|nested] 9+ messages in thread
* [tip:irq/urgent] genirq: Print threaded handler in spurious debug output 2011-05-31 6:56 [PATCH 1/3] irq/spurious: dump also the name of the threaded handler Sebastian Andrzej Siewior 2011-05-31 6:56 ` [PATCH 2/3] irq: handle spurios irq detection for threaded irqs Sebastian Andrzej Siewior 2011-05-31 6:56 ` [PATCH 3/3] irq: catch more wrong return values from interrupt handlers Sebastian Andrzej Siewior @ 2011-06-03 12:57 ` tip-bot for Sebastian Andrzej Siewior 2 siblings, 0 replies; 9+ messages in thread From: tip-bot for Sebastian Andrzej Siewior @ 2011-06-03 12:57 UTC (permalink / raw) To: linux-tip-commits; +Cc: linux-kernel, hpa, mingo, sebastian, tglx Commit-ID: ef26f20cd117eb3c185038ed7cbf7b235575751d Gitweb: http://git.kernel.org/tip/ef26f20cd117eb3c185038ed7cbf7b235575751d Author: Sebastian Andrzej Siewior <sebastian@breakpoint.cc> AuthorDate: Tue, 31 May 2011 08:56:10 +0200 Committer: Thomas Gleixner <tglx@linutronix.de> CommitDate: Fri, 3 Jun 2011 14:53:15 +0200 genirq: Print threaded handler in spurious debug output In forced threaded mode (or with an explicit threaded handler) we only see the primary handler, but not the threaded handler. Signed-off-by: Sebastian Andrzej Siewior <sebastian@breakpoint.cc> Link: http://lkml.kernel.org/r/1306824972-27067-1-git-send-email-sebastian@breakpoint.cc Signed-off-by: Thomas Gleixner <tglx@linutronix.de> --- kernel/irq/spurious.c | 9 +++++---- 1 files changed, 5 insertions(+), 4 deletions(-) diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c index dfbd550..c9a78ba 100644 --- a/kernel/irq/spurious.c +++ b/kernel/irq/spurious.c @@ -201,10 +201,11 @@ __report_bad_irq(unsigned int irq, struct irq_desc *desc, raw_spin_lock_irqsave(&desc->lock, flags); action = desc->action; while (action) { - printk(KERN_ERR "[<%p>]", action->handler); - print_symbol(" (%s)", - (unsigned long)action->handler); - printk("\n"); + printk(KERN_ERR "[<%p>] %pf", action->handler, action->handler); + if (action->thread_fn) + printk(KERN_CONT " threaded [<%p>] %pf", + action->thread_fn, action->thread_fn); + printk(KERN_CONT "\n"); action = action->next; } raw_spin_unlock_irqrestore(&desc->lock, flags); ^ permalink raw reply related [flat|nested] 9+ messages in thread
end of thread, other threads:[~2011-06-03 12:58 UTC | newest] Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2011-05-31 6:56 [PATCH 1/3] irq/spurious: dump also the name of the threaded handler Sebastian Andrzej Siewior 2011-05-31 6:56 ` [PATCH 2/3] irq: handle spurios irq detection for threaded irqs Sebastian Andrzej Siewior 2011-05-31 10:35 ` Thomas Gleixner 2011-06-01 6:33 ` [PATCH v2] " Sebastian Andrzej Siewior 2011-06-03 12:58 ` [tip:irq/urgent] irq: Handle " tip-bot for Sebastian Andrzej Siewior 2011-05-31 6:56 ` [PATCH 3/3] irq: catch more wrong return values from interrupt handlers Sebastian Andrzej Siewior 2011-05-31 10:32 ` Thomas Gleixner 2011-05-31 12:59 ` Sebastian Andrzej Siewior 2011-06-03 12:57 ` [tip:irq/urgent] genirq: Print threaded handler in spurious debug output tip-bot for Sebastian Andrzej Siewior
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).