History

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

Linus Torvalds committed 4 years ago

Commit 9692df02 parents ede4c6d 87078983 files · +33 −10Browse files

Showing the changes to kernel (3 of 3 files). Show all

Unified · Split

3 files
  1. kernel/irq/internals.h +2 −0
  2. kernel/irq/irqdesc.c +2 −0
  3. kernel/irq/manage.c +29 −10
kernel/irq/internals.h+2−0
@@ -29,12 +29,14 @@ extern struct irqaction chained_action; · 28 unmodified lines
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+2−0
@@ -407,6 +407,7 @@ static struct irq_desc *alloc_desc(int irq, int node, unsigned int flags, · 406 unmodified lines
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) · 162 unmodified lines
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+29−10
@@ -1248,6 +1248,31 @@ static void irq_wake_secondary(struct irq_desc *desc, struct irqaction *action) · 1247 unmodified lines
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) · 5 unmodified lines
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) · 418 unmodified lines
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) · 89 unmodified lines
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;