Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 288598
b: refs/heads/master
c: 7140ea1
h: refs/heads/master
v: v3
  • Loading branch information
Ido Yariv authored and Thomas Gleixner committed Mar 14, 2012
1 parent 77238d7 commit 8cca68f
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 29 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: df8d291f28aa1e8437c8f7816328a6516379c71b
refs/heads/master: 7140ea1980f2fae9c7aaeac5f6b35317e1389ee6
12 changes: 12 additions & 0 deletions trunk/kernel/irq/handle.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
60 changes: 32 additions & 28 deletions trunk/kernel/irq/manage.c
Original file line number Diff line number Diff line change
Expand Up @@ -759,6 +759,13 @@ static irqreturn_t irq_thread_fn(struct irq_desc *desc,
return ret;
}

static void wake_threads_waitq(struct irq_desc *desc)
{
if (atomic_dec_and_test(&desc->threads_active) &&
waitqueue_active(&desc->wait_for_threads))
wake_up(&desc->wait_for_threads);
}

/*
* Interrupt handler thread
*/
Expand All @@ -771,7 +778,6 @@ static int irq_thread(void *data)
struct irq_desc *desc = irq_to_desc(action->irq);
irqreturn_t (*handler_fn)(struct irq_desc *desc,
struct irqaction *action);
int wake;

if (force_irqthreads && test_bit(IRQTF_FORCED_THREAD,
&action->thread_flags))
Expand All @@ -783,39 +789,30 @@ static int irq_thread(void *data)
current->irq_thread = 1;

while (!irq_wait_for_interrupt(action)) {
irqreturn_t action_ret;

irq_thread_check_affinity(desc, action);

atomic_inc(&desc->threads_active);
action_ret = handler_fn(desc, action);
if (!noirqdebug)
note_interrupt(action->irq, desc, action_ret);

raw_spin_lock_irq(&desc->lock);
if (unlikely(irqd_irq_disabled(&desc->irq_data))) {
/*
* CHECKME: We might need a dedicated
* IRQ_THREAD_PENDING flag here, which
* retriggers the thread in check_irq_resend()
* but AFAICT IRQS_PENDING should be fine as it
* retriggers the interrupt itself --- tglx
*/
desc->istate |= IRQS_PENDING;
raw_spin_unlock_irq(&desc->lock);
} else {
irqreturn_t action_ret;

raw_spin_unlock_irq(&desc->lock);
action_ret = handler_fn(desc, action);
if (!noirqdebug)
note_interrupt(action->irq, desc, action_ret);
}

wake = atomic_dec_and_test(&desc->threads_active);

if (wake && waitqueue_active(&desc->wait_for_threads))
wake_up(&desc->wait_for_threads);
wake_threads_waitq(desc);
}

/* Prevent a stale desc->threads_oneshot */
irq_finalize_oneshot(desc, action, true);
/*
* This is the regular exit path. __free_irq() is stopping the
* thread via kthread_stop() after calling
* synchronize_irq(). So neither IRQTF_RUNTHREAD nor the
* oneshot mask bit should be set.
*
* Verify that this is true.
*/
if (WARN_ON(test_and_clear_bit(IRQTF_RUNTHREAD, &action->thread_flags)))
wake_threads_waitq(desc);

if (WARN_ON(desc->threads_oneshot & action->thread_mask))
irq_finalize_oneshot(desc, action, true);

/*
* Clear irq_thread. Otherwise exit_irq_thread() would make
Expand Down Expand Up @@ -845,6 +842,13 @@ void exit_irq_thread(void)

desc = irq_to_desc(action->irq);

/*
* If IRQTF_RUNTHREAD is set, we need to decrement
* desc->threads_active and wake possible waiters.
*/
if (test_and_clear_bit(IRQTF_RUNTHREAD, &action->thread_flags))
wake_threads_waitq(desc);

/* Prevent a stale desc->threads_oneshot */
irq_finalize_oneshot(desc, action, true);
}
Expand Down

0 comments on commit 8cca68f

Please sign in to comment.