[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250710085028.1070922-1-john.ernberg@actia.se>
Date: Thu, 10 Jul 2025 08:50:40 +0000
From: John Ernberg <john.ernberg@...ia.se>
To: Oliver Neukum <oneukum@...e.com>, Andrew Lunn <andrew+netdev@...n.ch>,
"David S . Miller" <davem@...emloft.net>, Eric Dumazet <edumazet@...gle.com>,
Jakub Kicinski <kuba@...nel.org>, Paolo Abeni <pabeni@...hat.com>
CC: Ming Lei <ming.lei@...onical.com>, "netdev@...r.kernel.org"
<netdev@...r.kernel.org>, "linux-usb@...r.kernel.org"
<linux-usb@...r.kernel.org>, "linux-kernel@...r.kernel.org"
<linux-kernel@...r.kernel.org>, John Ernberg <john.ernberg@...ia.se>,
"stable@...r.kernel.org" <stable@...r.kernel.org>
Subject: [PATCH] net: usbnet: Avoid potential RCU stall on LINK_CHANGE event
Having a Gemalto Cinterion PLS83-W modem attached to USB and activating the
cellular data link would sometimes yield the following RCU stall, leading
to a system freeze:
rcu: INFO: rcu_sched detected expedited stalls on CPUs/tasks: { 0-.... } 33108 jiffies s: 201 root: 0x1/.
rcu: blocking rcu_node structures (internal RCU debug):
Sending NMI from CPU 1 to CPUs 0:
NMI backtrace for cpu 0
Call trace:
arch_local_irq_enable+0x4/0x8
local_bh_enable+0x18/0x20
__netdev_alloc_skb+0x18c/0x1cc
rx_submit+0x68/0x1f8 [usbnet]
rx_alloc_submit+0x4c/0x74 [usbnet]
usbnet_bh+0x1d8/0x218 [usbnet]
usbnet_bh_tasklet+0x10/0x18 [usbnet]
tasklet_action_common+0xa8/0x110
tasklet_action+0x2c/0x34
handle_softirqs+0x2cc/0x3a0
__do_softirq+0x10/0x18
____do_softirq+0xc/0x14
call_on_irq_stack+0x24/0x34
do_softirq_own_stack+0x18/0x20
__irq_exit_rcu+0xa8/0xb8
irq_exit_rcu+0xc/0x30
el1_interrupt+0x34/0x48
el1h_64_irq_handler+0x14/0x1c
el1h_64_irq+0x68/0x6c
_raw_spin_unlock_irqrestore+0x38/0x48
xhci_urb_dequeue+0x1ac/0x45c [xhci_hcd]
unlink1+0xd4/0xdc [usbcore]
usb_hcd_unlink_urb+0x70/0xb0 [usbcore]
usb_unlink_urb+0x24/0x44 [usbcore]
unlink_urbs.constprop.0.isra.0+0x64/0xa8 [usbnet]
__handle_link_change+0x34/0x70 [usbnet]
usbnet_deferred_kevent+0x1c0/0x320 [usbnet]
process_scheduled_works+0x2d0/0x48c
worker_thread+0x150/0x1dc
kthread+0xd8/0xe8
ret_from_fork+0x10/0x20
It turns out that during the link activation a LINK_CHANGE event is emitted
which causes the active RX URBs to be unlinked, while that is happening
rx_submit() may begin pushing new URBs to the queue being emptied.
Causing the unlink queue to never empty.
Use the same approach as commit 43daa96b166c ("usbnet: Stop RX Q on MTU
change") and pause the RX queue while unlinking the URBs on LINK_CHANGE
as well.
Fixes: 4b49f58fff00 ("usbnet: handle link change")
Cc: stable@...r.kernel.org
Signed-off-by: John Ernberg <john.ernberg@...ia.se>
---
Tested on 6.12.20 and forward ported.
---
drivers/net/usb/usbnet.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index c04e715a4c2a..156f0e85a135 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1115,7 +1115,9 @@ static void __handle_link_change(struct usbnet *dev)
if (!netif_carrier_ok(dev->net)) {
/* kill URBs for reading packets to save bus bandwidth */
+ usbnet_pause_rx(dev);
unlink_urbs(dev, &dev->rxq);
+ usbnet_resume_rx(dev);
/*
* tx_timeout will unlink URBs for sending packets and
--
2.49.0
Powered by blists - more mailing lists