diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2012-07-13 13:29:45 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2012-07-25 06:46:38 -0400 |
commit | dc9b229a58dc0dfed34272ff26c6d5fd17c674e0 (patch) | |
tree | 722795c29e6037d971e76d52d607d7a70cbbefaf | |
parent | e2b34e311be3a57c9abcb927e37a57e38913714c (diff) |
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 553fb66da130..216b0ba109d7 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h | |||
@@ -349,6 +349,7 @@ enum { | |||
349 | IRQCHIP_MASK_ON_SUSPEND = (1 << 2), | 349 | IRQCHIP_MASK_ON_SUSPEND = (1 << 2), |
350 | IRQCHIP_ONOFFLINE_ENABLED = (1 << 3), | 350 | IRQCHIP_ONOFFLINE_ENABLED = (1 << 3), |
351 | IRQCHIP_SKIP_SET_WAKE = (1 << 4), | 351 | IRQCHIP_SKIP_SET_WAKE = (1 << 4), |
352 | IRQCHIP_ONESHOT_SAFE = (1 << 5), | ||
352 | }; | 353 | }; |
353 | 354 | ||
354 | /* This include will go away once we isolated irq_desc usage to core code */ | 355 | /* 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 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) | |||
960 | } | 960 | } |
961 | 961 | ||
962 | /* | 962 | /* |
963 | * Drivers are often written to work w/o knowledge about the | ||
964 | * underlying irq chip implementation, so a request for a | ||
965 | * threaded irq without a primary hard irq context handler | ||
966 | * requires the ONESHOT flag to be set. Some irq chips like | ||
967 | * MSI based interrupts are per se one shot safe. Check the | ||
968 | * chip flags, so we can avoid the unmask dance at the end of | ||
969 | * the threaded handler for those. | ||
970 | */ | ||
971 | if (desc->irq_data.chip->flags & IRQCHIP_ONESHOT_SAFE) | ||
972 | new->flags &= ~IRQF_ONESHOT; | ||
973 | |||
974 | /* | ||
963 | * The following block of code has to be executed atomically | 975 | * The following block of code has to be executed atomically |
964 | */ | 976 | */ |
965 | raw_spin_lock_irqsave(&desc->lock, flags); | 977 | raw_spin_lock_irqsave(&desc->lock, flags); |
@@ -1033,7 +1045,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) | |||
1033 | */ | 1045 | */ |
1034 | new->thread_mask = 1 << ffz(thread_mask); | 1046 | new->thread_mask = 1 << ffz(thread_mask); |
1035 | 1047 | ||
1036 | } else if (new->handler == irq_default_primary_handler) { | 1048 | } else if (new->handler == irq_default_primary_handler && |
1049 | !(desc->irq_data.chip->flags & IRQCHIP_ONESHOT_SAFE)) { | ||
1037 | /* | 1050 | /* |
1038 | * The interrupt was requested with handler = NULL, so | 1051 | * The interrupt was requested with handler = NULL, so |
1039 | * we use the default primary handler for it. But it | 1052 | * we use the default primary handler for it. But it |