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

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
29 * IRQTF_WARNED - warning "IRQ_WAKE_THREAD w/o thread_fn" has been printed29 * IRQTF_WARNED - warning "IRQ_WAKE_THREAD w/o thread_fn" has been printed
30 * IRQTF_AFFINITY - irq thread is requested to adjust affinity30 * IRQTF_AFFINITY - irq thread is requested to adjust affinity
31 * IRQTF_FORCED_THREAD - irq action is force threaded31 * IRQTF_FORCED_THREAD - irq action is force threaded
32 * IRQTF_READY - signals that irq thread is ready
32 */33 */
33enum {34enum {
34 IRQTF_RUNTHREAD,35 IRQTF_RUNTHREAD,
35 IRQTF_WARNED,36 IRQTF_WARNED,
36 IRQTF_AFFINITY,37 IRQTF_AFFINITY,
37 IRQTF_FORCED_THREAD,38 IRQTF_FORCED_THREAD,
39 IRQTF_READY,
38};40};
39 41
40/*42/*
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
407 lockdep_set_class(&desc->lock, &irq_desc_lock_class);407 lockdep_set_class(&desc->lock, &irq_desc_lock_class);
408 mutex_init(&desc->request_mutex);408 mutex_init(&desc->request_mutex);
409 init_rcu_head(&desc->rcu);409 init_rcu_head(&desc->rcu);
410 init_waitqueue_head(&desc->wait_for_threads);
410 411
411 desc_set_defaults(irq, desc, node, affinity, owner);412 desc_set_defaults(irq, desc, node, affinity, owner);
412 irqd_set(&desc->irq_data, flags);413 irqd_set(&desc->irq_data, flags);
@@ -575,6 +576,7 @@ int __init early_irq_init(void) · 162 unmodified lines
575 raw_spin_lock_init(&desc[i].lock);576 raw_spin_lock_init(&desc[i].lock);
576 lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);577 lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
577 mutex_init(&desc[i].request_mutex);578 mutex_init(&desc[i].request_mutex);
579 init_waitqueue_head(&desc[i].wait_for_threads);
578 desc_set_defaults(i, &desc[i], node, NULL, NULL);580 desc_set_defaults(i, &desc[i], node, NULL, NULL);
579 }581 }
580 return arch_early_irq_init();582 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
1248 raw_spin_unlock_irq(&desc->lock);1248 raw_spin_unlock_irq(&desc->lock);
1249}1249}
1250 1250
1251/*
1252 * Internal function to notify that a interrupt thread is ready.
1253 */
1254static 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 */
1265static 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
1251/*1276/*
1252 * Interrupt handler thread1277 * Interrupt handler thread
1253 */1278 */
@@ -1259,6 +1284,8 @@ static int irq_thread(void *data) · 5 unmodified lines
1259 irqreturn_t (*handler_fn)(struct irq_desc *desc,1284 irqreturn_t (*handler_fn)(struct irq_desc *desc,
1260 struct irqaction *action);1285 struct irqaction *action);
1261 1286
1287 irq_thread_set_ready(desc, action);
1288
1262 sched_set_fifo(current);1289 sched_set_fifo(current);
1263 1290
1264 if (force_irqthreads() && test_bit(IRQTF_FORCED_THREAD,1291 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
1683 }1710 }
1684 1711
1685 if (!shared) {1712 if (!shared) {
1686 init_waitqueue_head(&desc->wait_for_threads);
1687
1688 /* Setup the type (level, edge polarity) if configured: */1713 /* Setup the type (level, edge polarity) if configured: */
1689 if (new->flags & IRQF_TRIGGER_MASK) {1714 if (new->flags & IRQF_TRIGGER_MASK) {
1690 ret = __irq_set_trigger(desc,1715 ret = __irq_set_trigger(desc,
@@ -1780,14 +1805,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) · 89 unmodified lines
1780 1805
1781 irq_setup_timings(desc, new);1806 irq_setup_timings(desc, new);
1782 1807
1783 /*1808 wake_up_and_wait_for_irq_thread_ready(desc, new);
1784 * Strictly no need to wake it up, but hung_task complains1809 wake_up_and_wait_for_irq_thread_ready(desc, new->secondary);
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);
1791 1810
1792 register_irq_proc(irq, desc);1811 register_irq_proc(irq, desc);
1793 new->dir = NULL;1812 new->dir = NULL;