diff options
Diffstat (limited to 'kernel/irq/manage.c')
-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 0a8e8f059627..4c69326aa773 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
@@ -944,6 +944,18 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) | |||
944 | } | 944 | } |
945 | 945 | ||
946 | /* | 946 | /* |
947 | * Drivers are often written to work w/o knowledge about the | ||
948 | * underlying irq chip implementation, so a request for a | ||
949 | * threaded irq without a primary hard irq context handler | ||
950 | * requires the ONESHOT flag to be set. Some irq chips like | ||
951 | * MSI based interrupts are per se one shot safe. Check the | ||
952 | * chip flags, so we can avoid the unmask dance at the end of | ||
953 | * the threaded handler for those. | ||
954 | */ | ||
955 | if (desc->irq_data.chip->flags & IRQCHIP_ONESHOT_SAFE) | ||
956 | new->flags &= ~IRQF_ONESHOT; | ||
957 | |||
958 | /* | ||
947 | * The following block of code has to be executed atomically | 959 | * The following block of code has to be executed atomically |
948 | */ | 960 | */ |
949 | raw_spin_lock_irqsave(&desc->lock, flags); | 961 | raw_spin_lock_irqsave(&desc->lock, flags); |
@@ -1017,7 +1029,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) | |||
1017 | */ | 1029 | */ |
1018 | new->thread_mask = 1 << ffz(thread_mask); | 1030 | new->thread_mask = 1 << ffz(thread_mask); |
1019 | 1031 | ||
1020 | } else if (new->handler == irq_default_primary_handler) { | 1032 | } else if (new->handler == irq_default_primary_handler && |
1033 | !(desc->irq_data.chip->flags & IRQCHIP_ONESHOT_SAFE)) { | ||
1021 | /* | 1034 | /* |
1022 | * The interrupt was requested with handler = NULL, so | 1035 | * The interrupt was requested with handler = NULL, so |
1023 | * we use the default primary handler for it. But it | 1036 | * we use the default primary handler for it. But it |