aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/irq
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2014-02-14 19:55:19 -0500
committerThomas Gleixner <tglx@linutronix.de>2014-02-19 11:22:44 -0500
commita92444c6b2225a9115d661c950cb48a22aeace20 (patch)
treead76dd71c9fec1648469009cb356351ca23daef0 /kernel/irq
parent18258f7239a61d8929b8e0c7b6d46c446459074c (diff)
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
Diffstat (limited to 'kernel/irq')
-rw-r--r--kernel/irq/handle.c4
-rw-r--r--kernel/irq/internals.h1
-rw-r--r--kernel/irq/manage.c27
3 files changed, 30 insertions, 2 deletions
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index 131ca176b497..bfec453557b4 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)
51 "but no thread function available.", irq, action->name); 51 "but no thread function available.", irq, action->name);
52} 52}
53 53
54static void irq_wake_thread(struct irq_desc *desc, struct irqaction *action) 54void __irq_wake_thread(struct irq_desc *desc, struct irqaction *action)
55{ 55{
56 /* 56 /*
57 * In case the thread crashed and was killed we just pretend that 57 * 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)
157 break; 157 break;
158 } 158 }
159 159
160 irq_wake_thread(desc, action); 160 __irq_wake_thread(desc, action);
161 161
162 /* Fall through to add to randomness */ 162 /* Fall through to add to randomness */
163 case IRQ_HANDLED: 163 case IRQ_HANDLED:
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
index 001fa5bab490..d61ac29e32d0 100644
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -82,6 +82,7 @@ irqreturn_t handle_irq_event(struct irq_desc *desc);
82/* Resending of interrupts :*/ 82/* Resending of interrupts :*/
83void check_irq_resend(struct irq_desc *desc, unsigned int irq); 83void check_irq_resend(struct irq_desc *desc, unsigned int irq);
84bool irq_wait_for_poll(struct irq_desc *desc); 84bool irq_wait_for_poll(struct irq_desc *desc);
85void __irq_wake_thread(struct irq_desc *desc, struct irqaction *action);
85 86
86#ifdef CONFIG_PROC_FS 87#ifdef CONFIG_PROC_FS
87extern void register_irq_proc(unsigned int irq, struct irq_desc *desc); 88extern void register_irq_proc(unsigned int irq, struct irq_desc *desc);
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 274ba9238fb7..54eb5c99351b 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -911,6 +911,33 @@ static int irq_thread(void *data)
911 return 0; 911 return 0;
912} 912}
913 913
914/**
915 * irq_wake_thread - wake the irq thread for the action identified by dev_id
916 * @irq: Interrupt line
917 * @dev_id: Device identity for which the thread should be woken
918 *
919 */
920void irq_wake_thread(unsigned int irq, void *dev_id)
921{
922 struct irq_desc *desc = irq_to_desc(irq);
923 struct irqaction *action;
924 unsigned long flags;
925
926 if (!desc || WARN_ON(irq_settings_is_per_cpu_devid(desc)))
927 return;
928
929 raw_spin_lock_irqsave(&desc->lock, flags);
930 for (action = desc->action; action; action = action->next) {
931 if (action->dev_id == dev_id) {
932 if (action->thread)
933 __irq_wake_thread(desc, action);
934 break;
935 }
936 }
937 raw_spin_unlock_irqrestore(&desc->lock, flags);
938}
939EXPORT_SYMBOL_GPL(irq_wake_thread);
940
914static void irq_setup_forced_threading(struct irqaction *new) 941static void irq_setup_forced_threading(struct irqaction *new)
915{ 942{
916 if (!force_irqthreads) 943 if (!force_irqthreads)