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 | |
parent | e2b34e311be3a57c9abcb927e37a57e38913714c (diff) | |
download | linux-3.10-dc9b229a58dc0dfed34272ff26c6d5fd17c674e0.tar.gz linux-3.10-dc9b229a58dc0dfed34272ff26c6d5fd17c674e0.tar.bz2 linux-3.10-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>
-rw-r--r-- | include/linux/irq.h | 1 | ||||
-rw-r--r-- | kernel/irq/manage.c | 15 |
2 files changed, 15 insertions, 1 deletions
diff --git a/include/linux/irq.h b/include/linux/irq.h index 553fb66da13..216b0ba109d 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -349,6 +349,7 @@ enum { IRQCHIP_MASK_ON_SUSPEND = (1 << 2), IRQCHIP_ONOFFLINE_ENABLED = (1 << 3), IRQCHIP_SKIP_SET_WAKE = (1 << 4), + IRQCHIP_ONESHOT_SAFE = (1 << 5), }; /* This include will go away once we isolated irq_desc usage to core code */ diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 8c548232ba3..2e326d1ebec 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 |