diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2012-07-13 19:29:45 +0200 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2012-07-25 12:46:38 +0200 |
commit | dc9b229a58dc0dfed34272ff26c6d5fd17c674e0 (patch) | |
tree | 722795c29e6037d971e76d52d607d7a70cbbefaf /kernel | |
parent | e2b34e311be3a57c9abcb927e37a57e38913714c (diff) | |
download | linux-stable-dc9b229a58dc0dfed34272ff26c6d5fd17c674e0.tar.gz linux-stable-dc9b229a58dc0dfed34272ff26c6d5fd17c674e0.tar.bz2 linux-stable-dc9b229a58dc0dfed34272ff26c6d5fd17c674e0.zip |
genirq: Allow irq chips to mark themself oneshot safe
Some interrupt chips like MSI are oneshot safe by implementation. For
those interrupts we can avoid the mask/unmask sequence for threaded
interrupt handlers.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/alpine.LFD.2.02.1207132056540.32033@ionos
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Avi Kivity <avi@redhat.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Jan Kiszka <jan.kiszka@web.de>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/irq/manage.c | 15 |
1 files changed, 14 insertions, 1 deletions
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 8c548232ba39..2e326d1ebec1 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -960,6 +960,18 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) } /* + * Drivers are often written to work w/o knowledge about the + * underlying irq chip implementation, so a request for a + * threaded irq without a primary hard irq context handler + * requires the ONESHOT flag to be set. Some irq chips like + * MSI based interrupts are per se one shot safe. Check the + * chip flags, so we can avoid the unmask dance at the end of + * the threaded handler for those. + */ + if (desc->irq_data.chip->flags & IRQCHIP_ONESHOT_SAFE) + new->flags &= ~IRQF_ONESHOT; + + /* * The following block of code has to be executed atomically */ raw_spin_lock_irqsave(&desc->lock, flags); @@ -1033,7 +1045,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) */ new->thread_mask = 1 << ffz(thread_mask); - } else if (new->handler == irq_default_primary_handler) { + } else if (new->handler == irq_default_primary_handler && + !(desc->irq_data.chip->flags & IRQCHIP_ONESHOT_SAFE)) { /* * The interrupt was requested with handler = NULL, so * we use the default primary handler for it. But it |