Skip to content

Commit 9f5deb5

Browse files
jhovoldKAGA-KOKO
authored andcommitted
genirq: Fix software resend lockup and nested resend
The switch to using hlist for managing software resend of interrupts broke resend in at least two ways: First, unconditionally adding interrupt descriptors to the resend list can corrupt the list when the descriptor in question has already been added. This causes the resend tasklet to loop indefinitely with interrupts disabled as was recently reported with the Lenovo ThinkPad X13s after threaded NAPI was disabled in the ath11k WiFi driver. This bug is easily fixed by restoring the old semantics of irq_sw_resend() so that it can be called also for descriptors that have already been marked for resend. Second, the offending commit also broke software resend of nested interrupts by simply discarding the code that made sure that such interrupts are retriggered using the parent interrupt. Add back the corresponding code that adds the parent descriptor to the resend list. Fixes: bc06a9e ("genirq: Use hlist for managing resend handlers") Signed-off-by: Johan Hovold <johan+linaro@kernel.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Marc Zyngier <maz@kernel.org> Link: https://lore.kernel.org/lkml/20230809073432.4193-1-johan+linaro@kernel.org/ Link: https://lore.kernel.org/r/20230826154004.1417-1-johan+linaro@kernel.org
1 parent de99090 commit 9f5deb5

File tree

1 file changed

+6
-1
lines changed

1 file changed

+6
-1
lines changed

kernel/irq/resend.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,16 @@ static int irq_sw_resend(struct irq_desc *desc)
6868
*/
6969
if (!desc->parent_irq)
7070
return -EINVAL;
71+
72+
desc = irq_to_desc(desc->parent_irq);
73+
if (!desc)
74+
return -EINVAL;
7175
}
7276

7377
/* Add to resend_list and activate the softirq: */
7478
raw_spin_lock(&irq_resend_lock);
75-
hlist_add_head(&desc->resend_node, &irq_resend_list);
79+
if (hlist_unhashed(&desc->resend_node))
80+
hlist_add_head(&desc->resend_node, &irq_resend_list);
7681
raw_spin_unlock(&irq_resend_lock);
7782
tasklet_schedule(&resend_tasklet);
7883
return 0;

0 commit comments

Comments
 (0)