Skip to content

Commit 26f29b1

Browse files
edumazetPaolo Abeni
authored andcommitted
net: fix backlog_unlock_irq_restore() vs CONFIG_PREEMPT_RT
CONFIG_PREEMPT_RT is special, make this clear in backlog_lock_irq_save() and backlog_unlock_irq_restore(). The issue shows up with CONFIG_DEBUG_IRQFLAGS=y raw_local_irq_restore() called with IRQs enabled WARNING: kernel/locking/irqflag-debug.c:10 at warn_bogus_irq_restore+0xc/0x20 kernel/locking/irqflag-debug.c:10, CPU#1: aoe_tx0/1321 Modules linked in: CPU: 1 UID: 0 PID: 1321 Comm: aoe_tx0 Not tainted syzkaller #0 PREEMPT_{RT,(full)} Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/24/2026 RIP: 0010:warn_bogus_irq_restore+0xc/0x20 kernel/locking/irqflag-debug.c:10 Call Trace: <TASK> backlog_unlock_irq_restore net/core/dev.c:253 [inline] enqueue_to_backlog+0x525/0xcf0 net/core/dev.c:5347 netif_rx_internal+0x120/0x550 net/core/dev.c:5659 __netif_rx+0xa9/0x110 net/core/dev.c:5679 loopback_xmit+0x43a/0x660 drivers/net/loopback.c:90 __netdev_start_xmit include/linux/netdevice.h:5275 [inline] netdev_start_xmit include/linux/netdevice.h:5284 [inline] xmit_one net/core/dev.c:3864 [inline] dev_hard_start_xmit+0x2df/0x830 net/core/dev.c:3880 __dev_queue_xmit+0x16f4/0x3990 net/core/dev.c:4829 dev_queue_xmit include/linux/netdevice.h:3384 [inline] Fixes: 27a01c1 ("net: fully inline backlog_unlock_irq_restore()") Signed-off-by: Eric Dumazet <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Paolo Abeni <[email protected]>
1 parent 636fd32 commit 26f29b1

1 file changed

Lines changed: 12 additions & 5 deletions

File tree

net/core/dev.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -231,10 +231,13 @@ static bool use_backlog_threads(void)
231231
static inline void backlog_lock_irq_save(struct softnet_data *sd,
232232
unsigned long *flags)
233233
{
234-
if (IS_ENABLED(CONFIG_RPS) || use_backlog_threads())
234+
if (IS_ENABLED(CONFIG_PREEMPT_RT)) {
235235
spin_lock_irqsave(&sd->input_pkt_queue.lock, *flags);
236-
else
236+
} else {
237237
local_irq_save(*flags);
238+
if (IS_ENABLED(CONFIG_RPS) || use_backlog_threads())
239+
spin_lock(&sd->input_pkt_queue.lock);
240+
}
238241
}
239242

240243
static inline void backlog_lock_irq_disable(struct softnet_data *sd)
@@ -248,9 +251,13 @@ static inline void backlog_lock_irq_disable(struct softnet_data *sd)
248251
static inline void backlog_unlock_irq_restore(struct softnet_data *sd,
249252
unsigned long flags)
250253
{
251-
if (IS_ENABLED(CONFIG_RPS) || use_backlog_threads())
252-
spin_unlock(&sd->input_pkt_queue.lock);
253-
local_irq_restore(flags);
254+
if (IS_ENABLED(CONFIG_PREEMPT_RT)) {
255+
spin_unlock_irqrestore(&sd->input_pkt_queue.lock, flags);
256+
} else {
257+
if (IS_ENABLED(CONFIG_RPS) || use_backlog_threads())
258+
spin_unlock(&sd->input_pkt_queue.lock);
259+
local_irq_restore(flags);
260+
}
254261
}
255262

256263
static inline void backlog_unlock_irq_enable(struct softnet_data *sd)

0 commit comments

Comments
 (0)