diff options
Diffstat (limited to 'kernel/irq/handle.c')
-rw-r--r-- | kernel/irq/handle.c | 28 |
1 files changed, 22 insertions, 6 deletions
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index 470d08c82bbe..bdb180325551 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c | |||
@@ -54,14 +54,18 @@ static void warn_no_thread(unsigned int irq, struct irqaction *action) | |||
54 | static void irq_wake_thread(struct irq_desc *desc, struct irqaction *action) | 54 | static void irq_wake_thread(struct irq_desc *desc, struct irqaction *action) |
55 | { | 55 | { |
56 | /* | 56 | /* |
57 | * Wake up the handler thread for this action. In case the | 57 | * In case the thread crashed and was killed we just pretend that |
58 | * thread crashed and was killed we just pretend that we | 58 | * we handled the interrupt. The hardirq handler has disabled the |
59 | * handled the interrupt. The hardirq handler has disabled the | 59 | * device interrupt, so no irq storm is lurking. |
60 | * device interrupt, so no irq storm is lurking. If the | 60 | */ |
61 | if (action->thread->flags & PF_EXITING) | ||
62 | return; | ||
63 | |||
64 | /* | ||
65 | * Wake up the handler thread for this action. If the | ||
61 | * RUNTHREAD bit is already set, nothing to do. | 66 | * RUNTHREAD bit is already set, nothing to do. |
62 | */ | 67 | */ |
63 | if (test_bit(IRQTF_DIED, &action->thread_flags) || | 68 | if (test_and_set_bit(IRQTF_RUNTHREAD, &action->thread_flags)) |
64 | test_and_set_bit(IRQTF_RUNTHREAD, &action->thread_flags)) | ||
65 | return; | 69 | return; |
66 | 70 | ||
67 | /* | 71 | /* |
@@ -110,6 +114,18 @@ static void irq_wake_thread(struct irq_desc *desc, struct irqaction *action) | |||
110 | * threads_oneshot untouched and runs the thread another time. | 114 | * threads_oneshot untouched and runs the thread another time. |
111 | */ | 115 | */ |
112 | desc->threads_oneshot |= action->thread_mask; | 116 | desc->threads_oneshot |= action->thread_mask; |
117 | |||
118 | /* | ||
119 | * We increment the threads_active counter in case we wake up | ||
120 | * the irq thread. The irq thread decrements the counter when | ||
121 | * it returns from the handler or in the exit path and wakes | ||
122 | * up waiters which are stuck in synchronize_irq() when the | ||
123 | * active count becomes zero. synchronize_irq() is serialized | ||
124 | * against this code (hard irq handler) via IRQS_INPROGRESS | ||
125 | * like the finalize_oneshot() code. See comment above. | ||
126 | */ | ||
127 | atomic_inc(&desc->threads_active); | ||
128 | |||
113 | wake_up_process(action->thread); | 129 | wake_up_process(action->thread); |
114 | } | 130 | } |
115 | 131 | ||