Skip to content

Commit 9692df0

Browse files
committed
Merge tag 'irq-urgent-2022-05-08' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull irq fix from Thomas Gleixner: "A fix for the threaded interrupt core. A quick sequence of request/free_irq() can result in a hang because the interrupt thread did not reach the thread function and got stopped in the kthread core already. That leaves a state active counter arround which makes a invocation of synchronized_irq() on that interrupt hang forever. Ensure that the thread reached the thread function in request_irq() to prevent that" * tag 'irq-urgent-2022-05-08' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: genirq: Synchronize interrupt thread startup
2 parents ede4c6d + 8707898 commit 9692df0

3 files changed

Lines changed: 33 additions & 10 deletions

File tree

kernel/irq/internals.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,14 @@ extern struct irqaction chained_action;
2929
* IRQTF_WARNED - warning "IRQ_WAKE_THREAD w/o thread_fn" has been printed
3030
* IRQTF_AFFINITY - irq thread is requested to adjust affinity
3131
* IRQTF_FORCED_THREAD - irq action is force threaded
32+
* IRQTF_READY - signals that irq thread is ready
3233
*/
3334
enum {
3435
IRQTF_RUNTHREAD,
3536
IRQTF_WARNED,
3637
IRQTF_AFFINITY,
3738
IRQTF_FORCED_THREAD,
39+
IRQTF_READY,
3840
};
3941

4042
/*

kernel/irq/irqdesc.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,7 @@ static struct irq_desc *alloc_desc(int irq, int node, unsigned int flags,
407407
lockdep_set_class(&desc->lock, &irq_desc_lock_class);
408408
mutex_init(&desc->request_mutex);
409409
init_rcu_head(&desc->rcu);
410+
init_waitqueue_head(&desc->wait_for_threads);
410411

411412
desc_set_defaults(irq, desc, node, affinity, owner);
412413
irqd_set(&desc->irq_data, flags);
@@ -575,6 +576,7 @@ int __init early_irq_init(void)
575576
raw_spin_lock_init(&desc[i].lock);
576577
lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
577578
mutex_init(&desc[i].request_mutex);
579+
init_waitqueue_head(&desc[i].wait_for_threads);
578580
desc_set_defaults(i, &desc[i], node, NULL, NULL);
579581
}
580582
return arch_early_irq_init();

kernel/irq/manage.c

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,6 +1248,31 @@ static void irq_wake_secondary(struct irq_desc *desc, struct irqaction *action)
12481248
raw_spin_unlock_irq(&desc->lock);
12491249
}
12501250

1251+
/*
1252+
* Internal function to notify that a interrupt thread is ready.
1253+
*/
1254+
static void irq_thread_set_ready(struct irq_desc *desc,
1255+
struct irqaction *action)
1256+
{
1257+
set_bit(IRQTF_READY, &action->thread_flags);
1258+
wake_up(&desc->wait_for_threads);
1259+
}
1260+
1261+
/*
1262+
* Internal function to wake up a interrupt thread and wait until it is
1263+
* ready.
1264+
*/
1265+
static void wake_up_and_wait_for_irq_thread_ready(struct irq_desc *desc,
1266+
struct irqaction *action)
1267+
{
1268+
if (!action || !action->thread)
1269+
return;
1270+
1271+
wake_up_process(action->thread);
1272+
wait_event(desc->wait_for_threads,
1273+
test_bit(IRQTF_READY, &action->thread_flags));
1274+
}
1275+
12511276
/*
12521277
* Interrupt handler thread
12531278
*/
@@ -1259,6 +1284,8 @@ static int irq_thread(void *data)
12591284
irqreturn_t (*handler_fn)(struct irq_desc *desc,
12601285
struct irqaction *action);
12611286

1287+
irq_thread_set_ready(desc, action);
1288+
12621289
sched_set_fifo(current);
12631290

12641291
if (force_irqthreads() && test_bit(IRQTF_FORCED_THREAD,
@@ -1683,8 +1710,6 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
16831710
}
16841711

16851712
if (!shared) {
1686-
init_waitqueue_head(&desc->wait_for_threads);
1687-
16881713
/* Setup the type (level, edge polarity) if configured: */
16891714
if (new->flags & IRQF_TRIGGER_MASK) {
16901715
ret = __irq_set_trigger(desc,
@@ -1780,14 +1805,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
17801805

17811806
irq_setup_timings(desc, new);
17821807

1783-
/*
1784-
* Strictly no need to wake it up, but hung_task complains
1785-
* when no hard interrupt wakes the thread up.
1786-
*/
1787-
if (new->thread)
1788-
wake_up_process(new->thread);
1789-
if (new->secondary)
1790-
wake_up_process(new->secondary->thread);
1808+
wake_up_and_wait_for_irq_thread_ready(desc, new);
1809+
wake_up_and_wait_for_irq_thread_ready(desc, new->secondary);
17911810

17921811
register_irq_proc(irq, desc);
17931812
new->dir = NULL;

0 commit comments

Comments
 (0)