community inclusion
category: bugfix
bugzilla: RVCK-Project#246
Reference: RVCK-Project#247
--------------------------------
The PLIC silently drops a completion whose source is not enabled for the
target hart, and until it receives a completion it will not re-deliver
the source, so the device stops receiving interrupts.
During affinity migration plic_set_affinity() clears the old hart's
enable bit; if that lands between claim and completion, the completion
is dropped. For a direct PLIC IRQ, plic_irq_eoi() and plic_set_affinity()
are both under desc->lock and cannot race, but a PLIC IRQ backing a
chained irqchip issues the completion from chained_irq_exit() and reaches
plic_set_affinity() via the chained chip's ->irq_set_affinity() callback,
neither holding desc->lock.
Take the per-context enable_lock (already held by plic_toggle() when
clearing the enable bit) across plic_irq_eoi() so the affinity clear
cannot overlap the EOI; test the enable bit inside the critical section
and re-enable around the completion if it is clear. enable_lock nests
inside desc->lock, so no new lock ordering is introduced.
Signed-off-by: Bowen Pang <bowen.pang01@sophgo.com>
community inclusion
category: bugfix
bugzilla: #246