aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/irq/chip.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2009-08-13 06:17:22 -0400
committerThomas Gleixner <tglx@linutronix.de>2009-08-17 04:54:05 -0400
commitb25c340c195447afb1860da580fe2a85a6b652c5 (patch)
tree99578092c1e6100f50786e44a1a4fe9cfdb11662 /kernel/irq/chip.c
parentb2add73dbf93fd50f00564d7abc3e2b9aa9dd20c (diff)
genirq: Add oneshot support
For threaded interrupt handlers we expect the hard interrupt handler part to mask the interrupt on the originating device. The interrupt line itself is reenabled after the hard interrupt handler has executed. This requires access to the originating device from hard interrupt context which is not always possible. There are devices which can only be accessed via a bus (i2c, spi, ...). The bus access requires thread context. For such devices we need to keep the interrupt line masked until the threaded handler has executed. Add a new flag IRQF_ONESHOT which allows drivers to request that the interrupt is not unmasked after the hard interrupt context handler has been executed and the thread has been woken. The interrupt line is unmasked after the thread handler function has been executed. Note that for now IRQF_ONESHOT cannot be used with IRQF_SHARED to avoid complex accounting mechanisms. For oneshot interrupts the primary handler simply returns IRQ_WAKE_THREAD and does nothing else. A generic implementation irq_default_primary_handler() is provided to avoid useless copies all over the place. It is automatically installed when request_threaded_irq() is called with handler=NULL and thread_fn!=NULL. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: Mark Brown <broonie@opensource.wolfsonmicro.com> Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com> Cc: Trilok Soni <soni.trilok@gmail.com> Cc: Pavel Machek <pavel@ucw.cz> Cc: Brian Swetland <swetland@google.com> Cc: Joonyoung Shim <jy0922.shim@samsung.com> Cc: m.szyprowski@samsung.com Cc: t.fujak@samsung.com Cc: kyungmin.park@samsung.com, Cc: David Brownell <david-b@pacbell.net> Cc: Daniel Ribeiro <drwyrm@gmail.com> Cc: arve@android.com Cc: Barry Song <21cnbao@gmail.com>
Diffstat (limited to 'kernel/irq/chip.c')
-rw-r--r--kernel/irq/chip.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 13c68e71b726..b08c0d24f202 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -382,7 +382,10 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc)
382 382
383 spin_lock(&desc->lock); 383 spin_lock(&desc->lock);
384 desc->status &= ~IRQ_INPROGRESS; 384 desc->status &= ~IRQ_INPROGRESS;
385 if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask) 385
386 if (unlikely(desc->status & IRQ_ONESHOT))
387 desc->status |= IRQ_MASKED;
388 else if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)
386 desc->chip->unmask(irq); 389 desc->chip->unmask(irq);
387out_unlock: 390out_unlock:
388 spin_unlock(&desc->lock); 391 spin_unlock(&desc->lock);
@@ -478,8 +481,13 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc)
478 kstat_incr_irqs_this_cpu(irq, desc); 481 kstat_incr_irqs_this_cpu(irq, desc);
479 482
480 /* Start handling the irq */ 483 /* Start handling the irq */
481 if (desc->chip->ack) 484 if (unlikely(desc->status & IRQ_ONESHOT)) {
482 desc->chip->ack(irq); 485 desc->status |= IRQ_MASKED;
486 mask_ack_irq(desc, irq);
487 } else {
488 if (desc->chip->ack)
489 desc->chip->ack(irq);
490 }
483 491
484 /* Mark the IRQ currently in progress.*/ 492 /* Mark the IRQ currently in progress.*/
485 desc->status |= IRQ_INPROGRESS; 493 desc->status |= IRQ_INPROGRESS;