diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-08-26 20:34:29 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-08-26 20:34:29 +0300 |
commit | 3b35375f19fe87b5d8822ce01f917095d575ee28 (patch) | |
tree | 7866aa34432f779f2785569babc70d5f0f97d6d2 /kernel | |
parent | c313761337fb8fa7fc44296f0e10844505916208 (diff) | |
parent | 9f5deb551655a4cff04b21ecffdcdab75112da3a (diff) | |
download | linux-3b35375f19fe87b5d8822ce01f917095d575ee28.tar.xz |
Merge tag 'irq-urgent-2023-08-26' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull irq fix from Thomas Gleixner:
"A last minute fix for a regression introduced in the v6.5 merge
window.
The conversion of the software based interrupt resend mechanism to
hlist missed to add a check whether the descriptor is already enqueued
and dropped the interrupt descriptor lookup for nested interrupts.
The missing check whether the descriptor is already queued causes
hlist corruption and can be observed in the wild. The dropped parent
descriptor lookup has not yet caused problems, but it would result in
stale interrupt line in the worst case.
Add the missing enqueued check and bring the descriptor lookup back to
cure this"
* tag 'irq-urgent-2023-08-26' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
genirq: Fix software resend lockup and nested resend
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/irq/resend.c | 7 |
1 files changed, 6 insertions, 1 deletions
diff --git a/kernel/irq/resend.c b/kernel/irq/resend.c index edec335c0a7a..5f2c66860ac6 100644 --- a/kernel/irq/resend.c +++ b/kernel/irq/resend.c @@ -68,11 +68,16 @@ static int irq_sw_resend(struct irq_desc *desc) */ if (!desc->parent_irq) return -EINVAL; + + desc = irq_to_desc(desc->parent_irq); + if (!desc) + return -EINVAL; } /* Add to resend_list and activate the softirq: */ raw_spin_lock(&irq_resend_lock); - hlist_add_head(&desc->resend_node, &irq_resend_list); + if (hlist_unhashed(&desc->resend_node)) + hlist_add_head(&desc->resend_node, &irq_resend_list); raw_spin_unlock(&irq_resend_lock); tasklet_schedule(&resend_tasklet); return 0; |