All of lore.kernel.org
 help / color / mirror / Atom feed
* [patch 0/2] genirq: Add functions to avoid driver hackery
@ 2014-02-15  0:55 Thomas Gleixner
  2014-02-15  0:55 ` [patch 1/2] genirq: Provide synchronize_hardirq() Thomas Gleixner
  2014-02-15  0:55 ` [patch 2/2] genirq: Provide irq_wake_thread() Thomas Gleixner
  0 siblings, 2 replies; 7+ messages in thread
From: Thomas Gleixner @ 2014-02-15  0:55 UTC (permalink / raw)
  To: LKML; +Cc: Russell King, Chris Ball, linux-mmc, Ingo Molnar, Peter Zijlstra

Russell tricked me to look into the homebrewn kthread hackery of
drivers/mmc. I'm still trying to recover from that.

But it spurred an interesting discussion how to improve things and the
outcome was the following series of patches:

1) Provide means to synchronize only hard irq context

2) Provide means to trigger a threaded irq handler from any context

The main rationale is to cleanup the mess in drivers/mmc and other
places but each of the patches has a justification for itself
exemplified by the drivers/mmc use case, which is explained in detail
in the changelogs of the individual patches.

Russell has a working implementation for sdhci which relies on patch
#1 ready and quite some ideas how to make use of #2 to kill the
sdio_irq kthread hackery.

Thanks,

	tglx




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

* [patch 1/2] genirq: Provide synchronize_hardirq()
  2014-02-15  0:55 [patch 0/2] genirq: Add functions to avoid driver hackery Thomas Gleixner
@ 2014-02-15  0:55 ` Thomas Gleixner
  2014-02-15  9:50   ` Peter Zijlstra
  2014-02-19 16:27   ` [tip:irq/core] " tip-bot for Thomas Gleixner
  2014-02-15  0:55 ` [patch 2/2] genirq: Provide irq_wake_thread() Thomas Gleixner
  1 sibling, 2 replies; 7+ messages in thread
From: Thomas Gleixner @ 2014-02-15  0:55 UTC (permalink / raw)
  To: LKML; +Cc: Russell King, Chris Ball, linux-mmc, Ingo Molnar, Peter Zijlstra

[-- Attachment #1: genirq-synchronize-hardirq.patch --]
[-- Type: text/plain, Size: 4700 bytes --]

synchronize_irq() waits for hard irq and threaded handlers to complete
before returning. For some special cases we only need to make sure
that the hard interrupt part of the irq line is not in progress when
we disabled the - possibly shared - interrupt at the device level.

A proper use case for this was provided by Russell. The sdhci driver
requires some irq triggered functions to be run in thread context. The
current implementation of the thread context is a sdio private kthread
construct, which has quite some shortcomings. These can be avoided
when the thread is directly associated to the device interrupt via the
generic threaded irq infrastructure.

Though there is a corner case related to run time power management
where one side disables the device interrupts at the device level and
needs to make sure, that an already running hard interrupt handler has
completed before proceeding further. Though that hard interrupt
handler might wake the associated thread, which in turn can request
the runtime PM to reenable the device. Using synchronize_irq() leads
to an immediate deadlock of the irq thread waiting for the PM lock and
the synchronize_irq() waiting for the irq thread to complete.

Due to the fact that it is sufficient for this case to ensure that no
hard irq handler is executing a new function which avoids the check
for the thread is required.

Add a function, which just monitors the hard irq parts and ignores the
threaded handlers.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 include/linux/hardirq.h |    1 
 kernel/irq/manage.c     |   67 +++++++++++++++++++++++++++++++++---------------
 2 files changed, 48 insertions(+), 20 deletions(-)

Index: linux-2.6/include/linux/hardirq.h
===================================================================
--- linux-2.6.orig/include/linux/hardirq.h
+++ linux-2.6/include/linux/hardirq.h
@@ -9,6 +9,7 @@
 
 
 extern void synchronize_irq(unsigned int irq);
+extern void synchronize_hardirq(unsigned int irq);
 
 #if defined(CONFIG_TINY_RCU)
 
Index: linux-2.6/kernel/irq/manage.c
===================================================================
--- linux-2.6.orig/kernel/irq/manage.c
+++ linux-2.6/kernel/irq/manage.c
@@ -32,24 +32,10 @@ static int __init setup_forced_irqthread
 early_param("threadirqs", setup_forced_irqthreads);
 #endif
 
-/**
- *	synchronize_irq - wait for pending IRQ handlers (on other CPUs)
- *	@irq: interrupt number to wait for
- *
- *	This function waits for any pending IRQ handlers for this interrupt
- *	to complete before returning. If you use this function while
- *	holding a resource the IRQ handler may need you will deadlock.
- *
- *	This function may be called - with care - from IRQ context.
- */
-void synchronize_irq(unsigned int irq)
+static void __synchronize_hardirq(struct irq_desc *desc)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
 	bool inprogress;
 
-	if (!desc)
-		return;
-
 	do {
 		unsigned long flags;
 
@@ -67,12 +53,53 @@ void synchronize_irq(unsigned int irq)
 
 		/* Oops, that failed? */
 	} while (inprogress);
+}
 
-	/*
-	 * We made sure that no hardirq handler is running. Now verify
-	 * that no threaded handlers are active.
-	 */
-	wait_event(desc->wait_for_threads, !atomic_read(&desc->threads_active));
+/**
+ *	synchronize_hardirq - wait for pending hard IRQ handlers (on other CPUs)
+ *	@irq: interrupt number to wait for
+ *
+ *	This function waits for any pending hard IRQ handlers for this
+ *	interrupt to complete before returning. If you use this
+ *	function while holding a resource the IRQ handler may need you
+ *	will deadlock. It does not take associated threaded handlers into
+ *	account.
+ *
+ *	This function may be called - with care - from IRQ context.
+ */
+void synchronize_hardirq(unsigned int irq)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+
+	if (desc)
+		__synchronize_hardirq(desc);
+}
+EXPORT_SYMBOL(synchronize_hardirq);
+
+/**
+ *	synchronize_irq - wait for pending IRQ handlers (on other CPUs)
+ *	@irq: interrupt number to wait for
+ *
+ *	This function waits for any pending IRQ handlers for this interrupt
+ *	to complete before returning. If you use this function while
+ *	holding a resource the IRQ handler may need you will deadlock.
+ *
+ *	This function may be called - with care - from IRQ context.
+ */
+void synchronize_irq(unsigned int irq)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+
+	if (desc) {
+		__synchronize_hardirq(desc);
+		/*
+		 * We made sure that no hardirq handler is
+		 * running. Now verify that no threaded handlers are
+		 * active.
+		 */
+		wait_event(desc->wait_for_threads,
+			   !atomic_read(&desc->threads_active));
+	}
 }
 EXPORT_SYMBOL(synchronize_irq);
 



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

* [patch 2/2] genirq: Provide irq_wake_thread()
  2014-02-15  0:55 [patch 0/2] genirq: Add functions to avoid driver hackery Thomas Gleixner
  2014-02-15  0:55 ` [patch 1/2] genirq: Provide synchronize_hardirq() Thomas Gleixner
@ 2014-02-15  0:55 ` Thomas Gleixner
  2014-02-15  9:50   ` Peter Zijlstra
  2014-02-19 16:27   ` [tip:irq/core] " tip-bot for Thomas Gleixner
  1 sibling, 2 replies; 7+ messages in thread
From: Thomas Gleixner @ 2014-02-15  0:55 UTC (permalink / raw)
  To: LKML; +Cc: Russell King, Chris Ball, linux-mmc, Ingo Molnar, Peter Zijlstra

[-- Attachment #1: genirq-irq-kick-thread.patch --]
[-- Type: text/plain, Size: 4149 bytes --]

In course of the sdhci/sdio discussion with Russell about killing the
sdio kthread hackery we discovered the need to be able to wake an
interrupt thread from software.

The rationale for this is, that sdio hardware can lack proper
interrupt support for certain features. So the driver needs to poll
the status registers, but at the same time it needs to be woken up by
an hardware interrupt.

To be able to get rid of the home brewn kthread construct of sdio we
need a way to wake an irq thread independent of an actual hardware
interrupt.

Provide an irq_wake_thread() function which wakes up the thread which
is associated to a given dev_id. This allows sdio to invoke the irq
thread from the hardware irq handler via the IRQ_WAKE_THREAD return
value and provides a possibility to wake it via a timer for the
polling scenarios. That allows to simplify the sdio logic
significantly.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 include/linux/interrupt.h |    1 +
 kernel/irq/handle.c       |    4 ++--
 kernel/irq/internals.h    |    1 +
 kernel/irq/manage.c       |   27 +++++++++++++++++++++++++++
 4 files changed, 31 insertions(+), 2 deletions(-)

Index: linux-2.6/include/linux/interrupt.h
===================================================================
--- linux-2.6.orig/include/linux/interrupt.h
+++ linux-2.6/include/linux/interrupt.h
@@ -183,6 +183,7 @@ extern void disable_irq(unsigned int irq
 extern void disable_percpu_irq(unsigned int irq);
 extern void enable_irq(unsigned int irq);
 extern void enable_percpu_irq(unsigned int irq, unsigned int type);
+extern void irq_wake_thread(unsigned int irq, void *dev_id);
 
 /* The following three functions are for the core kernel use only. */
 extern void suspend_device_irqs(void);
Index: linux-2.6/kernel/irq/handle.c
===================================================================
--- linux-2.6.orig/kernel/irq/handle.c
+++ linux-2.6/kernel/irq/handle.c
@@ -51,7 +51,7 @@ static void warn_no_thread(unsigned int
 	       "but no thread function available.", irq, action->name);
 }
 
-static void irq_wake_thread(struct irq_desc *desc, struct irqaction *action)
+void __irq_wake_thread(struct irq_desc *desc, struct irqaction *action)
 {
 	/*
 	 * In case the thread crashed and was killed we just pretend that
@@ -157,7 +157,7 @@ handle_irq_event_percpu(struct irq_desc
 				break;
 			}
 
-			irq_wake_thread(desc, action);
+			__irq_wake_thread(desc, action);
 
 			/* Fall through to add to randomness */
 		case IRQ_HANDLED:
Index: linux-2.6/kernel/irq/internals.h
===================================================================
--- linux-2.6.orig/kernel/irq/internals.h
+++ linux-2.6/kernel/irq/internals.h
@@ -82,6 +82,7 @@ irqreturn_t handle_irq_event(struct irq_
 /* Resending of interrupts :*/
 void check_irq_resend(struct irq_desc *desc, unsigned int irq);
 bool irq_wait_for_poll(struct irq_desc *desc);
+void __irq_wake_thread(struct irq_desc *desc, struct irqaction *action);
 
 #ifdef CONFIG_PROC_FS
 extern void register_irq_proc(unsigned int irq, struct irq_desc *desc);
Index: linux-2.6/kernel/irq/manage.c
===================================================================
--- linux-2.6.orig/kernel/irq/manage.c
+++ linux-2.6/kernel/irq/manage.c
@@ -908,6 +908,33 @@ static int irq_thread(void *data)
 	return 0;
 }
 
+/**
+ *	irq_wake_thread - wake the irq thread for the action identified by dev_id
+ *	@irq:		Interrupt line
+ *	@dev_id:	Device identity for which the thread should be woken
+ *
+ */
+void irq_wake_thread(unsigned int irq, void *dev_id)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+	struct irqaction *action;
+	unsigned long flags;
+
+	if (!desc || WARN_ON(irq_settings_is_per_cpu_devid(desc)))
+		return;
+
+	raw_spin_lock_irqsave(&desc->lock, flags);
+	for (action = desc->action; action; action = action->next) {
+		if (action->dev_id == dev_id) {
+			if (action->thread)
+				__irq_wake_thread(desc, action);
+			break;
+		}
+	}
+	raw_spin_unlock_irqrestore(&desc->lock, flags);
+}
+EXPORT_SYMBOL_GPL(irq_wake_thread);
+
 static void irq_setup_forced_threading(struct irqaction *new)
 {
 	if (!force_irqthreads)



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

* Re: [patch 1/2] genirq: Provide synchronize_hardirq()
  2014-02-15  0:55 ` [patch 1/2] genirq: Provide synchronize_hardirq() Thomas Gleixner
@ 2014-02-15  9:50   ` Peter Zijlstra
  2014-02-19 16:27   ` [tip:irq/core] " tip-bot for Thomas Gleixner
  1 sibling, 0 replies; 7+ messages in thread
From: Peter Zijlstra @ 2014-02-15  9:50 UTC (permalink / raw)
  To: Thomas Gleixner; +Cc: LKML, Russell King, Chris Ball, linux-mmc, Ingo Molnar

On Sat, Feb 15, 2014 at 12:55:18AM -0000, Thomas Gleixner wrote:
> synchronize_irq() waits for hard irq and threaded handlers to complete
> before returning. For some special cases we only need to make sure
> that the hard interrupt part of the irq line is not in progress when
> we disabled the - possibly shared - interrupt at the device level.
> 
> A proper use case for this was provided by Russell. The sdhci driver
> requires some irq triggered functions to be run in thread context. The
> current implementation of the thread context is a sdio private kthread
> construct, which has quite some shortcomings. These can be avoided
> when the thread is directly associated to the device interrupt via the
> generic threaded irq infrastructure.
> 
> Though there is a corner case related to run time power management
> where one side disables the device interrupts at the device level and
> needs to make sure, that an already running hard interrupt handler has
> completed before proceeding further. Though that hard interrupt
> handler might wake the associated thread, which in turn can request
> the runtime PM to reenable the device. Using synchronize_irq() leads
> to an immediate deadlock of the irq thread waiting for the PM lock and
> the synchronize_irq() waiting for the irq thread to complete.
> 
> Due to the fact that it is sufficient for this case to ensure that no
> hard irq handler is executing a new function which avoids the check
> for the thread is required.
> 
> Add a function, which just monitors the hard irq parts and ignores the
> threaded handlers.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Acked-by: Peter Zijlstra <peterz@infradead.org>

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

* Re: [patch 2/2] genirq: Provide irq_wake_thread()
  2014-02-15  0:55 ` [patch 2/2] genirq: Provide irq_wake_thread() Thomas Gleixner
@ 2014-02-15  9:50   ` Peter Zijlstra
  2014-02-19 16:27   ` [tip:irq/core] " tip-bot for Thomas Gleixner
  1 sibling, 0 replies; 7+ messages in thread
From: Peter Zijlstra @ 2014-02-15  9:50 UTC (permalink / raw)
  To: Thomas Gleixner; +Cc: LKML, Russell King, Chris Ball, linux-mmc, Ingo Molnar

On Sat, Feb 15, 2014 at 12:55:19AM -0000, Thomas Gleixner wrote:
> In course of the sdhci/sdio discussion with Russell about killing the
> sdio kthread hackery we discovered the need to be able to wake an
> interrupt thread from software.
> 
> The rationale for this is, that sdio hardware can lack proper
> interrupt support for certain features. So the driver needs to poll
> the status registers, but at the same time it needs to be woken up by
> an hardware interrupt.
> 
> To be able to get rid of the home brewn kthread construct of sdio we
> need a way to wake an irq thread independent of an actual hardware
> interrupt.
> 
> Provide an irq_wake_thread() function which wakes up the thread which
> is associated to a given dev_id. This allows sdio to invoke the irq
> thread from the hardware irq handler via the IRQ_WAKE_THREAD return
> value and provides a possibility to wake it via a timer for the
> polling scenarios. That allows to simplify the sdio logic
> significantly.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Acked-by: Peter Zijlstra <peterz@infradead.org>

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

* [tip:irq/core] genirq: Provide synchronize_hardirq()
  2014-02-15  0:55 ` [patch 1/2] genirq: Provide synchronize_hardirq() Thomas Gleixner
  2014-02-15  9:50   ` Peter Zijlstra
@ 2014-02-19 16:27   ` tip-bot for Thomas Gleixner
  1 sibling, 0 replies; 7+ messages in thread
From: tip-bot for Thomas Gleixner @ 2014-02-19 16:27 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: linux-kernel, hpa, mingo, linux, peterz, chris, tglx

Commit-ID:  18258f7239a61d8929b8e0c7b6d46c446459074c
Gitweb:     http://git.kernel.org/tip/18258f7239a61d8929b8e0c7b6d46c446459074c
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Sat, 15 Feb 2014 00:55:18 +0000
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Wed, 19 Feb 2014 17:22:44 +0100

genirq: Provide synchronize_hardirq()

synchronize_irq() waits for hard irq and threaded handlers to complete
before returning. For some special cases we only need to make sure
that the hard interrupt part of the irq line is not in progress when
we disabled the - possibly shared - interrupt at the device level.

A proper use case for this was provided by Russell. The sdhci driver
requires some irq triggered functions to be run in thread context. The
current implementation of the thread context is a sdio private kthread
construct, which has quite some shortcomings. These can be avoided
when the thread is directly associated to the device interrupt via the
generic threaded irq infrastructure.

Though there is a corner case related to run time power management
where one side disables the device interrupts at the device level and
needs to make sure, that an already running hard interrupt handler has
completed before proceeding further. Though that hard interrupt
handler might wake the associated thread, which in turn can request
the runtime PM to reenable the device. Using synchronize_irq() leads
to an immediate deadlock of the irq thread waiting for the PM lock and
the synchronize_irq() waiting for the irq thread to complete.

Due to the fact that it is sufficient for this case to ensure that no
hard irq handler is executing a new function which avoids the check
for the thread is required.

Add a function, which just monitors the hard irq parts and ignores the
threaded handlers.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Russell King <linux@arm.linux.org.uk>
Cc: Chris Ball <chris@printf.net>
Acked-by: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20140215003823.653236081@linutronix.de

---
 include/linux/hardirq.h |  1 +
 kernel/irq/manage.c     | 70 +++++++++++++++++++++++++++++++++++--------------
 2 files changed, 51 insertions(+), 20 deletions(-)

diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
index 12d5f97..cba442e 100644
--- a/include/linux/hardirq.h
+++ b/include/linux/hardirq.h
@@ -9,6 +9,7 @@
 
 
 extern void synchronize_irq(unsigned int irq);
+extern void synchronize_hardirq(unsigned int irq);
 
 #if defined(CONFIG_TINY_RCU)
 
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 481a13c..274ba92 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -32,24 +32,10 @@ static int __init setup_forced_irqthreads(char *arg)
 early_param("threadirqs", setup_forced_irqthreads);
 #endif
 
-/**
- *	synchronize_irq - wait for pending IRQ handlers (on other CPUs)
- *	@irq: interrupt number to wait for
- *
- *	This function waits for any pending IRQ handlers for this interrupt
- *	to complete before returning. If you use this function while
- *	holding a resource the IRQ handler may need you will deadlock.
- *
- *	This function may be called - with care - from IRQ context.
- */
-void synchronize_irq(unsigned int irq)
+static void __synchronize_hardirq(struct irq_desc *desc)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
 	bool inprogress;
 
-	if (!desc)
-		return;
-
 	do {
 		unsigned long flags;
 
@@ -67,12 +53,56 @@ void synchronize_irq(unsigned int irq)
 
 		/* Oops, that failed? */
 	} while (inprogress);
+}
 
-	/*
-	 * We made sure that no hardirq handler is running. Now verify
-	 * that no threaded handlers are active.
-	 */
-	wait_event(desc->wait_for_threads, !atomic_read(&desc->threads_active));
+/**
+ *	synchronize_hardirq - wait for pending hard IRQ handlers (on other CPUs)
+ *	@irq: interrupt number to wait for
+ *
+ *	This function waits for any pending hard IRQ handlers for this
+ *	interrupt to complete before returning. If you use this
+ *	function while holding a resource the IRQ handler may need you
+ *	will deadlock. It does not take associated threaded handlers
+ *	into account.
+ *
+ *	Do not use this for shutdown scenarios where you must be sure
+ *	that all parts (hardirq and threaded handler) have completed.
+ *
+ *	This function may be called - with care - from IRQ context.
+ */
+void synchronize_hardirq(unsigned int irq)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+
+	if (desc)
+		__synchronize_hardirq(desc);
+}
+EXPORT_SYMBOL(synchronize_hardirq);
+
+/**
+ *	synchronize_irq - wait for pending IRQ handlers (on other CPUs)
+ *	@irq: interrupt number to wait for
+ *
+ *	This function waits for any pending IRQ handlers for this interrupt
+ *	to complete before returning. If you use this function while
+ *	holding a resource the IRQ handler may need you will deadlock.
+ *
+ *	This function may be called - with care - from IRQ context.
+ */
+void synchronize_irq(unsigned int irq)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+
+	if (desc) {
+		__synchronize_hardirq(desc);
+		/*
+		 * We made sure that no hardirq handler is
+		 * running. Now verify that no threaded handlers are
+		 * active.
+		 */
+		wait_event(desc->wait_for_threads,
+			   !atomic_read(&desc->threads_active));
+	}
 }
 EXPORT_SYMBOL(synchronize_irq);
 

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

* [tip:irq/core] genirq: Provide irq_wake_thread()
  2014-02-15  0:55 ` [patch 2/2] genirq: Provide irq_wake_thread() Thomas Gleixner
  2014-02-15  9:50   ` Peter Zijlstra
@ 2014-02-19 16:27   ` tip-bot for Thomas Gleixner
  1 sibling, 0 replies; 7+ messages in thread
From: tip-bot for Thomas Gleixner @ 2014-02-19 16:27 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: linux-kernel, hpa, mingo, linux, peterz, chris, tglx

Commit-ID:  a92444c6b2225a9115d661c950cb48a22aeace20
Gitweb:     http://git.kernel.org/tip/a92444c6b2225a9115d661c950cb48a22aeace20
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Sat, 15 Feb 2014 00:55:19 +0000
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Wed, 19 Feb 2014 17:22:44 +0100

genirq: Provide irq_wake_thread()

In course of the sdhci/sdio discussion with Russell about killing the
sdio kthread hackery we discovered the need to be able to wake an
interrupt thread from software.

The rationale for this is, that sdio hardware can lack proper
interrupt support for certain features. So the driver needs to poll
the status registers, but at the same time it needs to be woken up by
an hardware interrupt.

To be able to get rid of the home brewn kthread construct of sdio we
need a way to wake an irq thread independent of an actual hardware
interrupt.

Provide an irq_wake_thread() function which wakes up the thread which
is associated to a given dev_id. This allows sdio to invoke the irq
thread from the hardware irq handler via the IRQ_WAKE_THREAD return
value and provides a possibility to wake it via a timer for the
polling scenarios. That allows to simplify the sdio logic
significantly.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Chris Ball <chris@printf.net>
Acked-by: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20140215003823.772565780@linutronix.de

---
 include/linux/interrupt.h |  1 +
 kernel/irq/handle.c       |  4 ++--
 kernel/irq/internals.h    |  1 +
 kernel/irq/manage.c       | 27 +++++++++++++++++++++++++++
 4 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index a2678d3..c7bfac1 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -188,6 +188,7 @@ extern void disable_irq(unsigned int irq);
 extern void disable_percpu_irq(unsigned int irq);
 extern void enable_irq(unsigned int irq);
 extern void enable_percpu_irq(unsigned int irq, unsigned int type);
+extern void irq_wake_thread(unsigned int irq, void *dev_id);
 
 /* The following three functions are for the core kernel use only. */
 extern void suspend_device_irqs(void);
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index 131ca17..bfec453 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -51,7 +51,7 @@ static void warn_no_thread(unsigned int irq, struct irqaction *action)
 	       "but no thread function available.", irq, action->name);
 }
 
-static void irq_wake_thread(struct irq_desc *desc, struct irqaction *action)
+void __irq_wake_thread(struct irq_desc *desc, struct irqaction *action)
 {
 	/*
 	 * In case the thread crashed and was killed we just pretend that
@@ -157,7 +157,7 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)
 				break;
 			}
 
-			irq_wake_thread(desc, action);
+			__irq_wake_thread(desc, action);
 
 			/* Fall through to add to randomness */
 		case IRQ_HANDLED:
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
index 001fa5b..d61ac29 100644
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -82,6 +82,7 @@ irqreturn_t handle_irq_event(struct irq_desc *desc);
 /* Resending of interrupts :*/
 void check_irq_resend(struct irq_desc *desc, unsigned int irq);
 bool irq_wait_for_poll(struct irq_desc *desc);
+void __irq_wake_thread(struct irq_desc *desc, struct irqaction *action);
 
 #ifdef CONFIG_PROC_FS
 extern void register_irq_proc(unsigned int irq, struct irq_desc *desc);
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 274ba92..54eb5c9 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -911,6 +911,33 @@ static int irq_thread(void *data)
 	return 0;
 }
 
+/**
+ *	irq_wake_thread - wake the irq thread for the action identified by dev_id
+ *	@irq:		Interrupt line
+ *	@dev_id:	Device identity for which the thread should be woken
+ *
+ */
+void irq_wake_thread(unsigned int irq, void *dev_id)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+	struct irqaction *action;
+	unsigned long flags;
+
+	if (!desc || WARN_ON(irq_settings_is_per_cpu_devid(desc)))
+		return;
+
+	raw_spin_lock_irqsave(&desc->lock, flags);
+	for (action = desc->action; action; action = action->next) {
+		if (action->dev_id == dev_id) {
+			if (action->thread)
+				__irq_wake_thread(desc, action);
+			break;
+		}
+	}
+	raw_spin_unlock_irqrestore(&desc->lock, flags);
+}
+EXPORT_SYMBOL_GPL(irq_wake_thread);
+
 static void irq_setup_forced_threading(struct irqaction *new)
 {
 	if (!force_irqthreads)

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

end of thread, other threads:[~2014-02-19 16:29 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-02-15  0:55 [patch 0/2] genirq: Add functions to avoid driver hackery Thomas Gleixner
2014-02-15  0:55 ` [patch 1/2] genirq: Provide synchronize_hardirq() Thomas Gleixner
2014-02-15  9:50   ` Peter Zijlstra
2014-02-19 16:27   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2014-02-15  0:55 ` [patch 2/2] genirq: Provide irq_wake_thread() Thomas Gleixner
2014-02-15  9:50   ` Peter Zijlstra
2014-02-19 16:27   ` [tip:irq/core] " tip-bot for Thomas Gleixner

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.