History

workqueue: Use raise_softirq() to trigger softirq in irq_work handler

bh_pool_kick_normal() and bh_pool_kick_highpri() are registered via init_irq_work() without the IRQ_WORK_HARD_IRQ flag. On PREEMPT_RT, such irq_work items are processed by the per-CPU irq_workd kthread in preemptible task context with IRQs enabled. However, raise_softirq_irqoff() requires IRQs to be disabled. Calling it from irq_workd trips the lockdep assertion in __raise_softirq_irqoff() and the non-atomic update of the softirq pending mask can lose bits raised by an interrupt on the same CPU. Replace raise_softirq_irqoff() with raise_softirq() in the irq_work handlers.

Zqiang committed 4 months ago

Commit 7e2f2a31 parent 6eca8f91 file · +2 −2Browse files

Showing the changes to kernel/workqueue.c (1 of 1 file). Show all

Unified · Split

kernel/workqueue.c+2−2
@@ -8065,12 +8065,12 @@ static inline void wq_watchdog_init(void) { } · 8064 unmodified lines
80658065
80668066 static void bh_pool_kick_normal(struct irq_work *irq_work)
80678067 {
8068− raise_softirq_irqoff(TASKLET_SOFTIRQ);
8068+ raise_softirq(TASKLET_SOFTIRQ);
80698069 }
80708070
80718071 static void bh_pool_kick_highpri(struct irq_work *irq_work)
80728072 {
8073− raise_softirq_irqoff(HI_SOFTIRQ);
8073+ raise_softirq(HI_SOFTIRQ);
80748074 }
80758075
80768076 static void __init restrict_unbound_cpumask(const char *name, const struct cpumask *mask)