* [syzbot] [kernel?] INFO: rcu detected stall in kill
@ 2026-04-03 17:50 syzbot
2026-04-05 1:21 ` Forwarded: [PATCH] ath9k: defer reg_in URB resubmission to workqueue syzbot
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: syzbot @ 2026-04-03 17:50 UTC (permalink / raw)
To: anna-maria, frederic, linux-kernel, syzkaller-bugs, tglx
Hello,
syzbot found the following issue on:
HEAD commit: 9147566d8016 Merge tag 'sched_ext-for-7.0-rc6-fixes' of gi..
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=151c1516580000
kernel config: https://syzkaller.appspot.com/x/.config?x=6754c86e8d9e4c91
dashboard link: https://syzkaller.appspot.com/bug?extid=9b95da55ba5146a60734
compiler: Debian clang version 21.1.8 (++20251221033036+2078da43e25a-1~exp1~20251221153213.50), Debian LLD 21.1.8
syz repro: https://syzkaller.appspot.com/x/repro.syz?x=111973d6580000
C reproducer: https://syzkaller.appspot.com/x/repro.c?x=12070dda580000
Downloadable assets:
disk image: https://storage.googleapis.com/syzbot-assets/c0b15aadfaef/disk-9147566d.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/9df2af7be859/vmlinux-9147566d.xz
kernel image: https://storage.googleapis.com/syzbot-assets/87eba4cf352e/bzImage-9147566d.xz
IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+9b95da55ba5146a60734@syzkaller.appspotmail.com
rcu: INFO: rcu_preempt detected stalls on CPUs/tasks:
rcu: Tasks blocked on level-0 rcu_node (CPUs 0-1): P5969/1:b..l
rcu: (detected by 1, t=10502 jiffies, g=14521, q=2117 ncpus=2)
task:syz-executor state:R running task stack:22432 pid:5969 tgid:5969 ppid:5967 task_flags:0x400140 flags:0x00080000
Call Trace:
<TASK>
context_switch kernel/sched/core.c:5298 [inline]
__schedule+0x15dd/0x52d0 kernel/sched/core.c:6911
preempt_schedule_irq+0x4d/0xa0 kernel/sched/core.c:7238
irqentry_exit+0x599/0x620 kernel/entry/common.c:239
asm_sysvec_apic_timer_interrupt+0x1a/0x20 arch/x86/include/asm/idtentry.h:697
RIP: 0010:lock_release+0x2d7/0x3d0 kernel/locking/lockdep.c:5893
Code: 16 7b 11 00 00 00 00 eb b5 e8 45 73 0d 0a f7 c3 00 02 00 00 74 b9 65 48 8b 05 c5 d0 7a 11 48 3b 44 24 28 75 44 fb 48 83 c4 30 <5b> 41 5c 41 5d 41 5e 41 5f 5d e9 95 81 6e ff cc 48 8d 3d 72 64 73
RSP: 0018:ffffc90003aafd78 EFLAGS: 00000286
RAX: d3d4042ff14ac900 RBX: 0000000000000202 RCX: 0000000000000046
RDX: 0000000000000000 RSI: ffffffff8e16b29d RDI: ffffffff8c27d100
RBP: ffff8880290229d8 R08: ffffffff9011ccb7 R09: 1ffffffff2023996
R10: dffffc0000000000 R11: fffffbfff2023997 R12: 0000000000000000
R13: 0000000000000000 R14: ffffffff8e75e5e0 R15: ffff888029021e80
rcu_lock_release include/linux/rcupdate.h:322 [inline]
rcu_read_unlock include/linux/rcupdate.h:881 [inline]
kill_proc_info+0x168/0x180 kernel/signal.c:1481
kill_something_info kernel/signal.c:1577 [inline]
__do_sys_kill kernel/signal.c:3953 [inline]
__se_sys_kill+0xd9/0x460 kernel/signal.c:3947
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x14d/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7fb210b3dda7
RSP: 002b:00007ffe1e460eb8 EFLAGS: 00000217 ORIG_RAX: 000000000000003e
RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 00007fb210b3dda7
RDX: 0000000000000097 RSI: 0000000000000009 RDI: 0000000000000003
RBP: 00007ffe1e460efc R08: 7fffffffffffffff R09: 0000000000000000
R10: 4000000000000000 R11: 0000000000000217 R12: 0000000000000000
R13: 0000000000000064 R14: 000000000003f067 R15: 00007ffe1e460f50
</TASK>
rcu: rcu_preempt kthread starved for 3053 jiffies! g14521 f0x0 RCU_GP_WAIT_FQS(5) ->state=0x0 ->cpu=0
rcu: Unless rcu_preempt kthread gets sufficient CPU time, OOM is now expected behavior.
rcu: RCU grace-period kthread stack dump:
task:rcu_preempt state:R running task stack:27744 pid:16 tgid:16 ppid:2 task_flags:0x208040 flags:0x00080000
Call Trace:
<TASK>
context_switch kernel/sched/core.c:5298 [inline]
__schedule+0x15dd/0x52d0 kernel/sched/core.c:6911
__schedule_loop kernel/sched/core.c:6993 [inline]
schedule+0x164/0x360 kernel/sched/core.c:7008
schedule_timeout+0x158/0x2c0 kernel/time/sleep_timeout.c:99
rcu_gp_fqs_loop+0x312/0x11d0 kernel/rcu/tree.c:2095
rcu_gp_kthread+0x9e/0x2b0 kernel/rcu/tree.c:2297
kthread+0x388/0x470 kernel/kthread.c:436
ret_from_fork+0x51e/0xb90 arch/x86/kernel/process.c:158
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
</TASK>
rcu: Stack dump where RCU GP kthread last ran:
Sending NMI from CPU 1 to CPUs 0:
NMI backtrace for cpu 0
CPU: 0 UID: 0 PID: 3405 Comm: kworker/R-bat_e Not tainted syzkaller #0 PREEMPT(full)
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 03/18/2026
Workqueue: bat_events batadv_tt_purge
RIP: 0010:get_current arch/x86/include/asm/current.h:25 [inline]
RIP: 0010:__sanitizer_cov_trace_pc+0x8/0x70 kernel/kcov.c:216
Code: 8b 3d 04 8b 55 0c 48 89 de 5b e9 e3 99 5e 00 cc cc cc 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 f3 0f 1e fa 48 8b 04 24 <65> 48 8b 0d 28 db 56 11 65 8b 15 49 db 56 11 81 e2 00 01 ff 00 74
RSP: 0018:ffffc900000078f0 EFLAGS: 00000046
RAX: ffffffff878d4630 RBX: 0000000000000000 RCX: 0000000000000100
RDX: ffff888033120000 RSI: 0000000000000000 RDI: 0000000000000000
RBP: ffff888156eed200 R08: 0000000000000003 R09: 0000000000000004
R10: dffffc0000000000 R11: fffff52000000f0c R12: ffff88802b35bc00
R13: dffffc0000000000 R14: ffff888029c47000 R15: ffff888029c47408
FS: 0000000000000000(0000) GS:ffff888125457000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000557a11963a38 CR3: 00000000677c5000 CR4: 0000000000350ef0
Call Trace:
<IRQ>
dummy_validate_stream drivers/usb/gadget/udc/dummy_hcd.c:1244 [inline]
dummy_urb_enqueue+0x270/0x780 drivers/usb/gadget/udc/dummy_hcd.c:1282
usb_hcd_submit_urb+0x328/0x1b70 drivers/usb/core/hcd.c:1542
ath9k_hif_usb_reg_in_cb+0x4d5/0x6f0 drivers/net/wireless/ath/ath9k/hif_usb.c:790
__usb_hcd_giveback_urb+0x376/0x540 drivers/usb/core/hcd.c:1657
dummy_timer+0xbbd/0x45d0 drivers/usb/gadget/udc/dummy_hcd.c:1995
__run_hrtimer kernel/time/hrtimer.c:1785 [inline]
__hrtimer_run_queues+0x53a/0xcc0 kernel/time/hrtimer.c:1849
hrtimer_run_softirq+0x182/0x5a0 kernel/time/hrtimer.c:1866
handle_softirqs+0x22a/0x870 kernel/softirq.c:622
do_softirq+0x76/0xd0 kernel/softirq.c:523
</IRQ>
<TASK>
__local_bh_enable_ip+0xf8/0x130 kernel/softirq.c:450
spin_unlock_bh include/linux/spinlock.h:395 [inline]
batadv_tt_local_purge+0x2a7/0x340 net/batman-adv/translation-table.c:1315
batadv_tt_purge+0x35/0x9e0 net/batman-adv/translation-table.c:3509
process_one_work kernel/workqueue.c:3276 [inline]
process_scheduled_works+0xb6e/0x18c0 kernel/workqueue.c:3359
rescuer_thread+0x827/0x1130 kernel/workqueue.c:3583
kthread+0x388/0x470 kernel/kthread.c:436
ret_from_fork+0x51e/0xb90 arch/x86/kernel/process.c:158
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
</TASK>
---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.
syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
If the report is already addressed, let syzbot know by replying with:
#syz fix: exact-commit-title
If you want syzbot to run the reproducer, reply with:
#syz test: git://repo/address.git branch-or-commit-hash
If you attach or paste a git patch, syzbot will apply it before testing.
If you want to overwrite report's subsystems, reply with:
#syz set subsystems: new-subsystem
(See the list of subsystem names on the web dashboard)
If the report is a duplicate of another one, reply with:
#syz dup: exact-subject-of-another-report
If you want to undo deduplication, reply with:
#syz undup
^ permalink raw reply [flat|nested] 5+ messages in thread
* Forwarded: [PATCH] ath9k: defer reg_in URB resubmission to workqueue
2026-04-03 17:50 [syzbot] [kernel?] INFO: rcu detected stall in kill syzbot
@ 2026-04-05 1:21 ` syzbot
2026-04-05 2:19 ` Forwarded: [PATCH] ath9k: defer reg_in URB resubmission to workqueue to fix RCU stall syzbot
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: syzbot @ 2026-04-05 1:21 UTC (permalink / raw)
To: linux-kernel, syzkaller-bugs
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.
***
Subject: [PATCH] ath9k: defer reg_in URB resubmission to workqueue
Author: kartikey406@gmail.com
#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
ath9k_hif_usb_reg_in_cb() is a URB completion callback that
runs in softirq context via dummy_hcd's hrtimer which is
registered with HRTIMER_MODE_REL_SOFT.
Calling usb_submit_urb() directly from this softirq context
triggers a long synchronous chain:
dummy_urb_enqueue()
hrtimer_start(HRTIMER_MODE_REL_SOFT)
dummy_timer()
__usb_hcd_giveback_urb()
ath9k_hif_usb_reg_in_cb()
usb_submit_urb() <- back to start
This keeps CPU busy in softirq context indefinitely, starving
the rcu_preempt kthread and causing an RCU stall:
rcu: rcu_preempt kthread starved for 3053 jiffies!
rcu: Unless rcu_preempt kthread gets sufficient CPU time,
OOM is now expected behavior.
Fix this by deferring URB resubmission to a workqueue via
schedule_work(), allowing the softirq to exit quickly and
giving rcu_preempt kthread sufficient CPU time to process
the grace period.
Reported-by: syzbot+9b95da55ba5146a60734@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=9b95da55ba5146a60734
Link: https://syzkaller.appspot.com/bug?extid=9b95da55ba5146a60734
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
drivers/net/wireless/ath/ath9k/hif_usb.c | 38 +++++++++++++++++++-----
drivers/net/wireless/ath/ath9k/hif_usb.h | 2 ++
2 files changed, 32 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 8533b88974b2..38c0cabe52bf 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -731,12 +731,38 @@ static void ath9k_hif_usb_rx_cb(struct urb *urb)
kfree(rx_buf);
}
+static void ath9k_hif_usb_reg_in_resubmit(struct work_struct *work)
+{
+ struct rx_buf *rx_buf = container_of(work,
+ struct rx_buf,
+ work);
+ struct hif_device_usb *hif_dev = rx_buf->hif_dev;
+ struct urb *urb = rx_buf->urb;
+ int ret;
+
+ if (!hif_dev || !urb)
+ goto free_rx_buf;
+
+ usb_anchor_urb(urb, &hif_dev->reg_in_submitted);
+ ret = usb_submit_urb(urb, GFP_KERNEL);
+ if (ret) {
+ usb_unanchor_urb(urb);
+ goto free_skb;
+ }
+ return;
+
+free_skb:
+ kfree_skb(rx_buf->skb);
+free_rx_buf:
+ kfree(rx_buf);
+ urb->context = NULL;
+}
+
static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
{
struct rx_buf *rx_buf = urb->context;
struct hif_device_usb *hif_dev = rx_buf->hif_dev;
struct sk_buff *skb = rx_buf->skb;
- int ret;
if (!skb)
return;
@@ -786,13 +812,9 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
}
resubmit:
- usb_anchor_urb(urb, &hif_dev->reg_in_submitted);
- ret = usb_submit_urb(urb, GFP_ATOMIC);
- if (ret) {
- usb_unanchor_urb(urb);
- goto free_skb;
- }
-
+ rx_buf->urb = urb;
+ INIT_WORK(&rx_buf->work, ath9k_hif_usb_reg_in_resubmit);
+ schedule_work(&rx_buf->work);
return;
free_skb:
kfree_skb(skb);
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h
index b3e66b0485a5..7c2a8d2c1cca 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.h
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.h
@@ -89,6 +89,8 @@ struct tx_buf {
struct rx_buf {
struct sk_buff *skb;
struct hif_device_usb *hif_dev;
+ struct urb *urb;
+ struct work_struct work;
};
#define HIF_USB_TX_STOP BIT(0)
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Forwarded: [PATCH] ath9k: defer reg_in URB resubmission to workqueue to fix RCU stall
2026-04-03 17:50 [syzbot] [kernel?] INFO: rcu detected stall in kill syzbot
2026-04-05 1:21 ` Forwarded: [PATCH] ath9k: defer reg_in URB resubmission to workqueue syzbot
@ 2026-04-05 2:19 ` syzbot
2026-04-05 4:41 ` syzbot
2026-04-05 5:18 ` syzbot
3 siblings, 0 replies; 5+ messages in thread
From: syzbot @ 2026-04-05 2:19 UTC (permalink / raw)
To: linux-kernel, syzkaller-bugs
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.
***
Subject: [PATCH] ath9k: defer reg_in URB resubmission to workqueue to fix RCU stall
Author: kartikey406@gmail.com
#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
ath9k_hif_usb_reg_in_cb() is a URB completion callback that
runs in softirq context via dummy_hcd's hrtimer which is
registered with HRTIMER_MODE_REL_SOFT.
Calling usb_submit_urb() directly from this softirq context
triggers a long synchronous chain:
dummy_urb_enqueue()
hrtimer_start(HRTIMER_MODE_REL_SOFT)
dummy_timer()
__usb_hcd_giveback_urb()
ath9k_hif_usb_reg_in_cb()
usb_submit_urb() <- back to start
This keeps the CPU busy in softirq context indefinitely,
starving the rcu_preempt kthread and causing an RCU stall:
rcu: rcu_preempt kthread starved for 3053 jiffies!
rcu: Unless rcu_preempt kthread gets sufficient CPU time,
OOM is now expected behavior.
Fix this by introducing a small per-resubmission wrapper
struct (reg_in_work) that is freshly allocated on each URB
completion and carries its own work_struct. The resubmission
is then deferred to the system workqueue via schedule_work(),
allowing the softirq to exit quickly.
Using a fresh wrapper per completion avoids the races that
would arise from reusing a single embedded work_struct:
- INIT_WORK() is called on a newly allocated struct so
there is no risk of reinitialising a work item that is
still queued or running.
- schedule_work() always returns true so no resubmission
is silently dropped.
- usb_get_urb() is called before schedule_work() and
usb_put_urb() is called in the worker, ensuring the URB
remains valid for the lifetime of the work item.
On resubmission failure in the worker the original error
path is preserved: the skb and rx_buf are freed and
urb->context is set to NULL, matching the behaviour of the
original goto free_skb path.
Reported-by: syzbot+9b95da55ba5146a60734@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=9b95da55ba5146a60734
Link: https://syzkaller.appspot.com/bug?extid=9b95da55ba5146a60734
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
drivers/net/wireless/ath/ath9k/hif_usb.c | 53 ++++++++++++++++++++----
1 file changed, 45 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 8533b88974b2..3ce598167731 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -731,12 +731,43 @@ static void ath9k_hif_usb_rx_cb(struct urb *urb)
kfree(rx_buf);
}
+struct reg_in_work {
+ struct urb *urb;
+ struct hif_device_usb *hif_dev;
+ struct work_struct work;
+};
+
+static void ath9k_hif_usb_reg_in_resubmit(struct work_struct *work)
+{
+ struct reg_in_work *rw = container_of(work,
+ struct reg_in_work,
+ work);
+ struct urb *urb = rw->urb;
+ struct rx_buf *rx_buf = urb->context;
+
+ int ret;
+
+ usb_anchor_urb(rw->urb, &rw->hif_dev->reg_in_submitted);
+ ret = usb_submit_urb(rw->urb, GFP_KERNEL);
+ usb_put_urb(rw->urb);
+
+ if (ret) {
+ usb_unanchor_urb(rw->urb);
+ if (rx_buf) {
+ kfree_skb(rx_buf->skb);
+ kfree(rx_buf);
+ urb->context = NULL;
+ }
+ }
+
+ kfree(rw);
+}
+
static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
{
struct rx_buf *rx_buf = urb->context;
struct hif_device_usb *hif_dev = rx_buf->hif_dev;
struct sk_buff *skb = rx_buf->skb;
- int ret;
if (!skb)
return;
@@ -786,14 +817,20 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
}
resubmit:
- usb_anchor_urb(urb, &hif_dev->reg_in_submitted);
- ret = usb_submit_urb(urb, GFP_ATOMIC);
- if (ret) {
- usb_unanchor_urb(urb);
- goto free_skb;
+ {
+ struct reg_in_work *rw;
+
+ rw = kmalloc_obj(*rw, GFP_ATOMIC);
+ if (!rw)
+ goto free_skb;
+
+ rw->urb = urb;
+ rw->hif_dev = hif_dev;
+ usb_get_urb(urb);
+ INIT_WORK(&rw->work, ath9k_hif_usb_reg_in_resubmit);
+ schedule_work(&rw->work);
+ return;
}
-
- return;
free_skb:
kfree_skb(skb);
free_rx_buf:
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Forwarded: [PATCH] ath9k: defer reg_in URB resubmission to workqueue to fix RCU stall
2026-04-03 17:50 [syzbot] [kernel?] INFO: rcu detected stall in kill syzbot
2026-04-05 1:21 ` Forwarded: [PATCH] ath9k: defer reg_in URB resubmission to workqueue syzbot
2026-04-05 2:19 ` Forwarded: [PATCH] ath9k: defer reg_in URB resubmission to workqueue to fix RCU stall syzbot
@ 2026-04-05 4:41 ` syzbot
2026-04-05 5:18 ` syzbot
3 siblings, 0 replies; 5+ messages in thread
From: syzbot @ 2026-04-05 4:41 UTC (permalink / raw)
To: linux-kernel, syzkaller-bugs
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.
***
Subject: [PATCH] ath9k: defer reg_in URB resubmission to workqueue to fix RCU stall
Author: kartikey406@gmail.com
#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
ath9k_hif_usb_reg_in_cb() is a URB completion callback that
runs in softirq context via dummy_hcd's hrtimer which is
registered with HRTIMER_MODE_REL_SOFT.
Calling usb_submit_urb() directly from this softirq context
triggers a long synchronous chain:
dummy_urb_enqueue()
hrtimer_start(HRTIMER_MODE_REL_SOFT)
dummy_timer()
__usb_hcd_giveback_urb()
ath9k_hif_usb_reg_in_cb()
usb_submit_urb() <- back to start
This keeps the CPU busy in softirq context indefinitely,
starving the rcu_preempt kthread and causing an RCU stall:
rcu: rcu_preempt kthread starved for 3053 jiffies!
rcu: Unless rcu_preempt kthread gets sufficient CPU time,
OOM is now expected behavior.
Fix this by introducing a small per-resubmission wrapper
struct (reg_in_work) that is freshly allocated on each URB
completion and carries its own work_struct. The resubmission
is then deferred to the system workqueue via schedule_work(),
allowing the softirq to exit quickly.
Using a fresh wrapper per completion avoids races that would
arise from reusing a single embedded work_struct:
- INIT_WORK() is called on a newly allocated struct so
there is no risk of reinitialising a work item that is
still queued or running.
- schedule_work() on a fresh work_struct always succeeds
so no resubmission is ever silently dropped.
- usb_get_urb() is called before schedule_work() and
usb_put_urb() is called last in the worker after all
URB accesses are complete, ensuring the URB remains
valid for the entire lifetime of the work item.
On resubmission failure in the worker the original error
path is preserved: skb and rx_buf are freed and
urb->context is set to NULL before dropping the URB
reference, matching the behaviour of the original
goto free_skb path.
Reported-by: syzbot+9b95da55ba5146a60734@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=9b95da55ba5146a60734
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
drivers/net/wireless/ath/ath9k/hif_usb.c | 53 ++++++++++++++++++++----
1 file changed, 45 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 8533b88974b2..0f9536b2d0a2 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -731,12 +731,43 @@ static void ath9k_hif_usb_rx_cb(struct urb *urb)
kfree(rx_buf);
}
+struct reg_in_work {
+ struct urb *urb;
+ struct hif_device_usb *hif_dev;
+ struct work_struct work;
+};
+
+static void ath9k_hif_usb_reg_in_resubmit(struct work_struct *work)
+{
+ struct reg_in_work *rw = container_of(work,
+ struct reg_in_work,
+ work);
+ struct urb *urb = rw->urb;
+ struct rx_buf *rx_buf = urb->context;
+
+ int ret;
+
+ usb_anchor_urb(rw->urb, &rw->hif_dev->reg_in_submitted);
+ ret = usb_submit_urb(rw->urb, GFP_KERNEL);
+
+ if (ret) {
+ usb_unanchor_urb(rw->urb);
+ if (rx_buf) {
+ kfree_skb(rx_buf->skb);
+ kfree(rx_buf);
+ urb->context = NULL;
+ }
+ }
+
+ usb_put_urb(urb);
+ kfree(rw);
+}
+
static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
{
struct rx_buf *rx_buf = urb->context;
struct hif_device_usb *hif_dev = rx_buf->hif_dev;
struct sk_buff *skb = rx_buf->skb;
- int ret;
if (!skb)
return;
@@ -786,14 +817,20 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
}
resubmit:
- usb_anchor_urb(urb, &hif_dev->reg_in_submitted);
- ret = usb_submit_urb(urb, GFP_ATOMIC);
- if (ret) {
- usb_unanchor_urb(urb);
- goto free_skb;
+ {
+ struct reg_in_work *rw;
+
+ rw = kmalloc_obj(*rw, GFP_ATOMIC);
+ if (!rw)
+ goto free_skb;
+
+ rw->urb = urb;
+ rw->hif_dev = hif_dev;
+ usb_get_urb(urb);
+ INIT_WORK(&rw->work, ath9k_hif_usb_reg_in_resubmit);
+ schedule_work(&rw->work);
+ return;
}
-
- return;
free_skb:
kfree_skb(skb);
free_rx_buf:
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Forwarded: [PATCH] ath9k: defer reg_in URB resubmission to workqueue to fix RCU stall
2026-04-03 17:50 [syzbot] [kernel?] INFO: rcu detected stall in kill syzbot
` (2 preceding siblings ...)
2026-04-05 4:41 ` syzbot
@ 2026-04-05 5:18 ` syzbot
3 siblings, 0 replies; 5+ messages in thread
From: syzbot @ 2026-04-05 5:18 UTC (permalink / raw)
To: linux-kernel, syzkaller-bugs
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.
***
Subject: [PATCH] ath9k: defer reg_in URB resubmission to workqueue to fix RCU stall
Author: kartikey406@gmail.com
#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
ath9k_hif_usb_reg_in_cb() is a URB completion callback that
runs in softirq context via dummy_hcd's hrtimer which is
registered with HRTIMER_MODE_REL_SOFT.
Calling usb_submit_urb() directly from this softirq context
triggers a long synchronous chain:
dummy_urb_enqueue()
hrtimer_start(HRTIMER_MODE_REL_SOFT)
dummy_timer()
__usb_hcd_giveback_urb()
ath9k_hif_usb_reg_in_cb()
usb_submit_urb() <- back to start
This keeps the CPU busy in softirq context indefinitely,
starving the rcu_preempt kthread and causing an RCU stall:
rcu: rcu_preempt kthread starved for 3053 jiffies!
rcu: Unless rcu_preempt kthread gets sufficient CPU time,
OOM is now expected behavior.
Fix this by introducing a small per-resubmission wrapper
struct (reg_in_work) that is freshly allocated on each URB
completion and carries its own work_struct. The resubmission
is deferred to a dedicated ordered workqueue (reg_in_wq)
via queue_work(), allowing the softirq to exit quickly.
Using a fresh wrapper per completion avoids races that would
arise from reusing a single embedded work_struct:
- INIT_WORK() is called on a newly allocated struct so
there is no risk of reinitialising a work item that is
still queued or running.
- queue_work() on a fresh work_struct always succeeds so
no resubmission is ever silently dropped.
- usb_get_urb() is called before queue_work() and
usb_put_urb() is called last in the worker after all
URB accesses are complete, ensuring the URB remains
valid for the entire lifetime of the work item.
A dedicated ordered workqueue is used instead of the system
workqueue to allow proper synchronization on disconnect.
destroy_workqueue() in ath9k_hif_usb_dealloc_reg_in_urbs()
drains all pending resubmissions before hif_dev is freed,
preventing use-after-free when the device is disconnected
while work items are still pending.
On resubmission failure in the worker the original error
path is preserved: skb and rx_buf are freed and
urb->context is set to NULL before dropping the URB
reference, matching the behaviour of the original
goto free_skb path.
Reported-by: syzbot+9b95da55ba5146a60734@syzkaller.appspotmail.com
Link: https://syzkaller.appspot.com/bug?extid=9b95da55ba5146a60734
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
drivers/net/wireless/ath/ath9k/hif_usb.c | 58 ++++++++++++++++++++----
drivers/net/wireless/ath/ath9k/hif_usb.h | 1 +
2 files changed, 51 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 8533b88974b2..370764681749 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -731,12 +731,43 @@ static void ath9k_hif_usb_rx_cb(struct urb *urb)
kfree(rx_buf);
}
+struct reg_in_work {
+ struct urb *urb;
+ struct hif_device_usb *hif_dev;
+ struct work_struct work;
+};
+
+static void ath9k_hif_usb_reg_in_resubmit(struct work_struct *work)
+{
+ struct reg_in_work *rw = container_of(work,
+ struct reg_in_work,
+ work);
+ struct urb *urb = rw->urb;
+ struct rx_buf *rx_buf = urb->context;
+
+ int ret;
+
+ usb_anchor_urb(rw->urb, &rw->hif_dev->reg_in_submitted);
+ ret = usb_submit_urb(rw->urb, GFP_KERNEL);
+
+ if (ret) {
+ usb_unanchor_urb(rw->urb);
+ if (rx_buf) {
+ kfree_skb(rx_buf->skb);
+ kfree(rx_buf);
+ urb->context = NULL;
+ }
+ }
+
+ usb_put_urb(urb);
+ kfree(rw);
+}
+
static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
{
struct rx_buf *rx_buf = urb->context;
struct hif_device_usb *hif_dev = rx_buf->hif_dev;
struct sk_buff *skb = rx_buf->skb;
- int ret;
if (!skb)
return;
@@ -786,14 +817,20 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
}
resubmit:
- usb_anchor_urb(urb, &hif_dev->reg_in_submitted);
- ret = usb_submit_urb(urb, GFP_ATOMIC);
- if (ret) {
- usb_unanchor_urb(urb);
- goto free_skb;
+ {
+ struct reg_in_work *rw;
+
+ rw = kmalloc_obj(*rw, GFP_ATOMIC);
+ if (!rw)
+ goto free_skb;
+
+ rw->urb = urb;
+ rw->hif_dev = hif_dev;
+ usb_get_urb(urb);
+ INIT_WORK(&rw->work, ath9k_hif_usb_reg_in_resubmit);
+ queue_work(hif_dev->reg_in_wq, &rw->work);
+ return;
}
-
- return;
free_skb:
kfree_skb(skb);
free_rx_buf:
@@ -959,6 +996,8 @@ static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
static void ath9k_hif_usb_dealloc_reg_in_urbs(struct hif_device_usb *hif_dev)
{
usb_kill_anchored_urbs(&hif_dev->reg_in_submitted);
+ if (hif_dev->reg_in_wq)
+ destroy_workqueue(hif_dev->reg_in_wq);
}
static int ath9k_hif_usb_alloc_reg_in_urbs(struct hif_device_usb *hif_dev)
@@ -969,6 +1008,9 @@ static int ath9k_hif_usb_alloc_reg_in_urbs(struct hif_device_usb *hif_dev)
int i, ret;
init_usb_anchor(&hif_dev->reg_in_submitted);
+ hif_dev->reg_in_wq = alloc_ordered_workqueue("ath9k_reg_in", 0);
+ if (!hif_dev->reg_in_wq)
+ return -ENOMEM;
for (i = 0; i < MAX_REG_IN_URB_NUM; i++) {
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h
index b3e66b0485a5..38f17a12fd5f 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.h
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.h
@@ -124,6 +124,7 @@ struct hif_device_usb {
struct usb_anchor regout_submitted;
struct usb_anchor rx_submitted;
struct usb_anchor reg_in_submitted;
+ struct workqueue_struct *reg_in_wq;
struct usb_anchor mgmt_submitted;
struct sk_buff *remain_skb;
char fw_name[64];
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-04-05 5:18 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-03 17:50 [syzbot] [kernel?] INFO: rcu detected stall in kill syzbot
2026-04-05 1:21 ` Forwarded: [PATCH] ath9k: defer reg_in URB resubmission to workqueue syzbot
2026-04-05 2:19 ` Forwarded: [PATCH] ath9k: defer reg_in URB resubmission to workqueue to fix RCU stall syzbot
2026-04-05 4:41 ` syzbot
2026-04-05 5:18 ` syzbot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox