summaryrefslogtreecommitdiff
path: root/kernel/irq/handle.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-03-20 10:28:56 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2012-03-20 10:28:56 -0700
commit0bbfcaff9b2a69c71a95e6902253487ab30cb498 (patch)
treef422bbfb8ba57909bf6e43f1d560b3f056cc3c61 /kernel/irq/handle.c
parent5928a2b60cfdbad730f93696acab142d0b607280 (diff)
parente04268b0effc0ceea366c50b3107baad9edadafa (diff)
Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull irq/core changes for v3.4 from Ingo Molnar * 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: genirq: Remove paranoid warnons and bogus fixups genirq: Flush the irq thread on synchronization genirq: Get rid of unnecessary IRQTF_DIED flag genirq: No need to check IRQTF_DIED before stopping a thread handler genirq: Get rid of unnecessary irqaction field in task_struct genirq: Fix incorrect check for forced IRQ thread handler softirq: Reduce invoke_softirq() code duplication genirq: Fix long-term regression in genirq irq_set_irq_type() handling x86-32/irq: Don't switch to irq stack for a user-mode irq
Diffstat (limited to 'kernel/irq/handle.c')
-rw-r--r--kernel/irq/handle.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index 470d08c82bbe..6ff84e6a954c 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -60,7 +60,7 @@ static void irq_wake_thread(struct irq_desc *desc, struct irqaction *action)
* device interrupt, so no irq storm is lurking. If the
* RUNTHREAD bit is already set, nothing to do.
*/
- if (test_bit(IRQTF_DIED, &action->thread_flags) ||
+ if ((action->thread->flags & PF_EXITING) ||
test_and_set_bit(IRQTF_RUNTHREAD, &action->thread_flags))
return;
@@ -110,6 +110,18 @@ static void irq_wake_thread(struct irq_desc *desc, struct irqaction *action)
* threads_oneshot untouched and runs the thread another time.
*/
desc->threads_oneshot |= action->thread_mask;
+
+ /*
+ * We increment the threads_active counter in case we wake up
+ * the irq thread. The irq thread decrements the counter when
+ * it returns from the handler or in the exit path and wakes
+ * up waiters which are stuck in synchronize_irq() when the
+ * active count becomes zero. synchronize_irq() is serialized
+ * against this code (hard irq handler) via IRQS_INPROGRESS
+ * like the finalize_oneshot() code. See comment above.
+ */
+ atomic_inc(&desc->threads_active);
+
wake_up_process(action->thread);
}