All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] genirq: spurious irq detection for threaded irqs
@ 2010-03-04 10:30 Uwe Kleine-König
  2010-03-04 22:26 ` Thomas Gleixner
  0 siblings, 1 reply; 6+ messages in thread
From: Uwe Kleine-König @ 2010-03-04 10:30 UTC (permalink / raw)
  To: linux-kernel; +Cc: Thomas Gleixner, Ingo Molnar

For threaded irqs the top half returns IRQ_WAKE_THREAD.  Don't treat
that value like IRQ_HANDLED for the spurious check.  Instead check the
return value of the threaded handler to be able to detect stuck irqs
that only have threaded handlers and no top half that can detect the
problem.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@elte.hu>
---
 include/linux/irq.h   |    2 ++
 kernel/irq/handle.c   |    6 ------
 kernel/irq/manage.c   |    7 ++++++-
 kernel/irq/spurious.c |   17 +++++++++++++++--
 4 files changed, 23 insertions(+), 9 deletions(-)

diff --git a/include/linux/irq.h b/include/linux/irq.h
index 451481c..f261765 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -323,6 +323,8 @@ static inline void generic_handle_irq(unsigned int irq)
 }
 
 /* Handling of unhandled and spurious interrupts: */
+extern void note_threaded_interrupt(unsigned int irq, struct irq_desc *desc,
+			   irqreturn_t action_ret);
 extern void note_interrupt(unsigned int irq, struct irq_desc *desc,
 			   irqreturn_t action_ret);
 
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index 814940e..3f63947 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -383,12 +383,6 @@ irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action)
 		switch (ret) {
 		case IRQ_WAKE_THREAD:
 			/*
-			 * Set result to handled so the spurious check
-			 * does not trigger.
-			 */
-			ret = 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 eb6078c..81fdc45 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -557,12 +557,17 @@ static int irq_thread(void *data)
 			desc->status |= IRQ_PENDING;
 			raw_spin_unlock_irq(&desc->lock);
 		} else {
+			irqreturn_t action_ret;
+
 			raw_spin_unlock_irq(&desc->lock);
 
-			action->thread_fn(action->irq, action->dev_id);
+			action_ret = action->thread_fn(action->irq, action->dev_id);
 
 			if (oneshot)
 				irq_finalize_oneshot(action->irq, desc);
+
+			if (!noirqdebug)
+				note_threaded_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 89fb90a..56395fd 100644
--- a/kernel/irq/spurious.c
+++ b/kernel/irq/spurious.c
@@ -213,8 +213,8 @@ try_misrouted_irq(unsigned int irq, struct irq_desc *desc,
 	return action && (action->flags & IRQF_IRQPOLL);
 }
 
-void note_interrupt(unsigned int irq, struct irq_desc *desc,
-		    irqreturn_t action_ret)
+void note_threaded_interrupt(unsigned int irq, struct irq_desc *desc,
+		irqreturn_t action_ret)
 {
 	if (unlikely(action_ret != IRQ_HANDLED)) {
 		/*
@@ -262,6 +262,19 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc,
 	desc->irqs_unhandled = 0;
 }
 
+void note_interrupt(unsigned int irq, struct irq_desc *desc,
+		irqreturn_t action_ret)
+{
+	if (action_ret == IRQ_WAKE_THREAD)
+		/* handled in irq_thread() when the threaded handler returns */
+		return;
+
+	/* don't report IRQ_WAKE_THREAD | IRQ_HANDLED as bogus return value */
+	action_ret &= ~IRQ_WAKE_THREAD;
+
+	note_threaded_interrupt(irq, desc, action_ret);
+}
+
 int noirqdebug __read_mostly;
 
 int noirqdebug_setup(char *str)
-- 
1.7.0


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

* Re: [PATCH] genirq: spurious irq detection for threaded irqs
  2010-03-04 10:30 [PATCH] genirq: spurious irq detection for threaded irqs Uwe Kleine-König
@ 2010-03-04 22:26 ` Thomas Gleixner
  2010-03-05  7:58   ` Uwe Kleine-König
  2010-03-05 15:18   ` [PATCH v2] " Uwe Kleine-König
  0 siblings, 2 replies; 6+ messages in thread
From: Thomas Gleixner @ 2010-03-04 22:26 UTC (permalink / raw)
  To: Uwe Kleine-König; +Cc: linux-kernel, Ingo Molnar

[-- Attachment #1: Type: TEXT/PLAIN, Size: 995 bytes --]

On Thu, 4 Mar 2010, Uwe Kleine-König wrote:
> -void note_interrupt(unsigned int irq, struct irq_desc *desc,
> -		    irqreturn_t action_ret)
> +void note_threaded_interrupt(unsigned int irq, struct irq_desc *desc,
> +		irqreturn_t action_ret)
>  {
>  	if (unlikely(action_ret != IRQ_HANDLED)) {
>  		/*
> @@ -262,6 +262,19 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc,
>  	desc->irqs_unhandled = 0;
>  }
>  
> +void note_interrupt(unsigned int irq, struct irq_desc *desc,
> +		irqreturn_t action_ret)
> +{
> +	if (action_ret == IRQ_WAKE_THREAD)
> +		/* handled in irq_thread() when the threaded handler returns */
> +		return;
> +
> +	/* don't report IRQ_WAKE_THREAD | IRQ_HANDLED as bogus return value */
> +	action_ret &= ~IRQ_WAKE_THREAD;
> +
> +	note_threaded_interrupt(irq, desc, action_ret);
> +}
> +

We don't need an extra function for that. A simple

	if (action_ret & IRQ_WAKE_THREAD)
		return;

in note_interrupt() is sufficient to cover everything.

Thanks,

	tglx

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

* Re: [PATCH] genirq: spurious irq detection for threaded irqs
  2010-03-04 22:26 ` Thomas Gleixner
@ 2010-03-05  7:58   ` Uwe Kleine-König
  2010-03-05 15:18   ` [PATCH v2] " Uwe Kleine-König
  1 sibling, 0 replies; 6+ messages in thread
From: Uwe Kleine-König @ 2010-03-05  7:58 UTC (permalink / raw)
  To: Thomas Gleixner; +Cc: linux-kernel, Ingo Molnar

On Thu, Mar 04, 2010 at 11:26:20PM +0100, Thomas Gleixner wrote:
> On Thu, 4 Mar 2010, Uwe Kleine-König wrote:
> > -void note_interrupt(unsigned int irq, struct irq_desc *desc,
> > -		    irqreturn_t action_ret)
> > +void note_threaded_interrupt(unsigned int irq, struct irq_desc *desc,
> > +		irqreturn_t action_ret)
> >  {
> >  	if (unlikely(action_ret != IRQ_HANDLED)) {
> >  		/*
> > @@ -262,6 +262,19 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc,
> >  	desc->irqs_unhandled = 0;
> >  }
> >  
> > +void note_interrupt(unsigned int irq, struct irq_desc *desc,
> > +		irqreturn_t action_ret)
> > +{
> > +	if (action_ret == IRQ_WAKE_THREAD)
> > +		/* handled in irq_thread() when the threaded handler returns */
> > +		return;
> > +
> > +	/* don't report IRQ_WAKE_THREAD | IRQ_HANDLED as bogus return value */
> > +	action_ret &= ~IRQ_WAKE_THREAD;
> > +
> > +	note_threaded_interrupt(irq, desc, action_ret);
> > +}
> > +
> 
> We don't need an extra function for that. A simple
> 
> 	if (action_ret & IRQ_WAKE_THREAD)
> 		return;
> 
> in note_interrupt() is sufficient to cover everything.
With your suggestion if action_ret == IRQ_WAKE_THREAD | IRQ_HANDLED then
the IRQ_HANDLED bit doesn't get noted.  Does that matter?

But still you're right about the extra function.  Assuming a threaded
handler doesn't return IRQ_WAKE_THREAD my note_interrupt does the same
as note_threaded_interrupt.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

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

* [PATCH v2] genirq: spurious irq detection for threaded irqs
  2010-03-04 22:26 ` Thomas Gleixner
  2010-03-05  7:58   ` Uwe Kleine-König
@ 2010-03-05 15:18   ` Uwe Kleine-König
  2010-03-05 20:16     ` Thomas Gleixner
  1 sibling, 1 reply; 6+ messages in thread
From: Uwe Kleine-König @ 2010-03-05 15:18 UTC (permalink / raw)
  To: linux-kernel; +Cc: Thomas Gleixner, Ingo Molnar

For threaded irqs the top half returns IRQ_WAKE_THREAD.  Don't treat
that value like IRQ_HANDLED for the spurious check.  Instead check the
return value of the threaded handler to be able to detect stuck irqs
that only have threaded handlers and no top half that can detect the
problem.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@elte.hu>
---
Hello,

changed since v1:

 - use note_interrupt for the threaded handler's return value, getting rid of
   note_threaded_interrupt.  The only downside is that a threaded handler
   returning IRQ_WAKE_THREAD remains uncatched now.

Best regards
Uwe

 kernel/irq/handle.c   |    6 ------
 kernel/irq/manage.c   |    8 +++++++-
 kernel/irq/spurious.c |    7 +++++++
 3 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index 76d5a67..a466dc6 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -381,12 +381,6 @@ irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action)
 		switch (ret) {
 		case IRQ_WAKE_THREAD:
 			/*
-			 * Set result to handled so the spurious check
-			 * does not trigger.
-			 */
-			ret = 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 eb6078c..9e1ff55 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -557,12 +557,18 @@ static int irq_thread(void *data)
 			desc->status |= IRQ_PENDING;
 			raw_spin_unlock_irq(&desc->lock);
 		} else {
+			irqreturn_t action_ret;
+
 			raw_spin_unlock_irq(&desc->lock);
 
-			action->thread_fn(action->irq, action->dev_id);
+			action_ret = action->thread_fn(action->irq,
+					action->dev_id);
 
 			if (oneshot)
 				irq_finalize_oneshot(action->irq, desc);
+
+			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 89fb90a..fc5c6e6 100644
--- a/kernel/irq/spurious.c
+++ b/kernel/irq/spurious.c
@@ -216,6 +216,13 @@ try_misrouted_irq(unsigned int irq, struct irq_desc *desc,
 void note_interrupt(unsigned int irq, struct irq_desc *desc,
 		    irqreturn_t action_ret)
 {
+	if (action_ret == IRQ_WAKE_THREAD)
+		/* handled in irq_thread() when the threaded handler returns */
+		return;
+
+	/* don't report IRQ_WAKE_THREAD | IRQ_HANDLED as bogus return value */
+	action_ret &= ~IRQ_WAKE_THREAD;
+
 	if (unlikely(action_ret != IRQ_HANDLED)) {
 		/*
 		 * If we are seeing only the odd spurious IRQ caused by
-- 
1.7.0


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

* Re: [PATCH v2] genirq: spurious irq detection for threaded irqs
  2010-03-05 15:18   ` [PATCH v2] " Uwe Kleine-König
@ 2010-03-05 20:16     ` Thomas Gleixner
  2010-03-08  9:01       ` Uwe Kleine-König
  0 siblings, 1 reply; 6+ messages in thread
From: Thomas Gleixner @ 2010-03-05 20:16 UTC (permalink / raw)
  To: Uwe Kleine-König; +Cc: linux-kernel, Ingo Molnar

[-- Attachment #1: Type: TEXT/PLAIN, Size: 948 bytes --]

On Fri, 5 Mar 2010, Uwe Kleine-König wrote:

> For threaded irqs the top half returns IRQ_WAKE_THREAD.  Don't treat
> that value like IRQ_HANDLED for the spurious check.  Instead check the
> return value of the threaded handler to be able to detect stuck irqs
> that only have threaded handlers and no top half that can detect the
> problem.
> 
> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ingo Molnar <mingo@elte.hu>
> ---
> Hello,
> 
> changed since v1:
> 
>  - use note_interrupt for the threaded handler's return value, getting rid of
>    note_threaded_interrupt.  The only downside is that a threaded handler
>    returning IRQ_WAKE_THREAD remains uncatched now.

Well that's easy to fix.
 
> +			if (!noirqdebug)
> +				note_interrupt(action->irq, desc, action_ret);

  				note_interrupt(action->irq, desc,
  					       action_ret & ~IRQ_WAKE_THREAD);
Thanks,

	tglx

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

* Re: [PATCH v2] genirq: spurious irq detection for threaded irqs
  2010-03-05 20:16     ` Thomas Gleixner
@ 2010-03-08  9:01       ` Uwe Kleine-König
  0 siblings, 0 replies; 6+ messages in thread
From: Uwe Kleine-König @ 2010-03-08  9:01 UTC (permalink / raw)
  To: Thomas Gleixner; +Cc: linux-kernel, Ingo Molnar

Hey Thomas,

On Fri, Mar 05, 2010 at 09:16:53PM +0100, Thomas Gleixner wrote:
> On Fri, 5 Mar 2010, Uwe Kleine-König wrote:
> 
> > For threaded irqs the top half returns IRQ_WAKE_THREAD.  Don't treat
> > that value like IRQ_HANDLED for the spurious check.  Instead check the
> > return value of the threaded handler to be able to detect stuck irqs
> > that only have threaded handlers and no top half that can detect the
> > problem.
> > 
> > Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> > Cc: Thomas Gleixner <tglx@linutronix.de>
> > Cc: Ingo Molnar <mingo@elte.hu>
> > ---
> > Hello,
> > 
> > changed since v1:
> > 
> >  - use note_interrupt for the threaded handler's return value, getting rid of
> >    note_threaded_interrupt.  The only downside is that a threaded handler
> >    returning IRQ_WAKE_THREAD remains uncatched now.
> 
> Well that's easy to fix.
>  
> > +			if (!noirqdebug)
> > +				note_interrupt(action->irq, desc, action_ret);
> 
>   				note_interrupt(action->irq, desc,
>   					       action_ret & ~IRQ_WAKE_THREAD);
Hmmm, this makes IRQ_WAKE_THREAD be noted as IRQ_NONE.
If this is intended it IMHO deserves a comment.  Something like:

	/*
	 * The threaded handler must return IRQ_NONE or IRQ_HANDLED.
	 * As IRQ_WAKE_THREAD is handled special by note_interrupt
	 * report it as IRQ_NONE.
	 */

Well and with that approach (IRQ_WAKE_THREAD | IRQ_HANDLED) is handled
as IRQ_HANDLED, but I think I start wasting time.

Actually I don't care what we do here, should I resend with action_ret &
~IRQ_WAKE_THREAD and the comment?

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

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

end of thread, other threads:[~2010-03-08  9:01 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-03-04 10:30 [PATCH] genirq: spurious irq detection for threaded irqs Uwe Kleine-König
2010-03-04 22:26 ` Thomas Gleixner
2010-03-05  7:58   ` Uwe Kleine-König
2010-03-05 15:18   ` [PATCH v2] " Uwe Kleine-König
2010-03-05 20:16     ` Thomas Gleixner
2010-03-08  9:01       ` Uwe Kleine-König

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.