diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2014-02-15 00:55:19 +0000 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2014-02-19 17:22:44 +0100 |
commit | a92444c6b2225a9115d661c950cb48a22aeace20 (patch) | |
tree | ad76dd71c9fec1648469009cb356351ca23daef0 /kernel/irq/manage.c | |
parent | 18258f7239a61d8929b8e0c7b6d46c446459074c (diff) | |
download | blackbird-op-linux-a92444c6b2225a9115d661c950cb48a22aeace20.tar.gz blackbird-op-linux-a92444c6b2225a9115d661c950cb48a22aeace20.zip |
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/manage.c')
-rw-r--r-- | kernel/irq/manage.c | 27 |
1 files changed, 27 insertions, 0 deletions
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) 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) |