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.
Showing the changes to kernel/workqueue.c (1 of 1 file). Show all
Unified · Split
| @@ -8065,12 +8065,12 @@ static inline void wq_watchdog_init(void) { } · 8064 unmodified lines | ||
| 8065 | 8065 | |
| 8066 | 8066 | static void bh_pool_kick_normal(struct irq_work *irq_work) |
| 8067 | 8067 | { |
| 8068 | − raise_softirq_irqoff(TASKLET_SOFTIRQ); | |
| 8068 | + raise_softirq(TASKLET_SOFTIRQ); | |
| 8069 | 8069 | } |
| 8070 | 8070 | |
| 8071 | 8071 | static void bh_pool_kick_highpri(struct irq_work *irq_work) |
| 8072 | 8072 | { |
| 8073 | − raise_softirq_irqoff(HI_SOFTIRQ); | |
| 8073 | + raise_softirq(HI_SOFTIRQ); | |
| 8074 | 8074 | } |
| 8075 | 8075 | |
| 8076 | 8076 | static void __init restrict_unbound_cpumask(const char *name, const struct cpumask *mask) |