]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net: usb: r8152: fix resume reset deadlock
authorSergey Senozhatsky <senozhatsky@chromium.org>
Thu, 29 Jan 2026 03:10:30 +0000 (12:10 +0900)
committerJakub Kicinski <kuba@kernel.org>
Sat, 31 Jan 2026 02:51:11 +0000 (18:51 -0800)
rtl8152 can trigger device reset during reset which
potentially can result in a deadlock:

 **** DPM device timeout after 10 seconds; 15 seconds until panic ****
 Call Trace:
 <TASK>
 schedule+0x483/0x1370
 schedule_preempt_disabled+0x15/0x30
 __mutex_lock_common+0x1fd/0x470
 __rtl8152_set_mac_address+0x80/0x1f0
 dev_set_mac_address+0x7f/0x150
 rtl8152_post_reset+0x72/0x150
 usb_reset_device+0x1d0/0x220
 rtl8152_resume+0x99/0xc0
 usb_resume_interface+0x3e/0xc0
 usb_resume_both+0x104/0x150
 usb_resume+0x22/0x110

The problem is that rtl8152 resume calls reset under
tp->control mutex while reset basically re-enters rtl8152
and attempts to acquire the same tp->control lock once
again.

Reset INACCESSIBLE device outside of tp->control mutex
scope to avoid recursive mutex_lock() deadlock.

Fixes: 4933b066fefb ("r8152: If inaccessible at resume time, issue a reset")
Reviewed-by: Douglas Anderson <dianders@chromium.org>
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
Link: https://patch.msgid.link/20260129031106.3805887-1-senozhatsky@chromium.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/usb/r8152.c

index fa519258386070e798cbc662f1ea52eebf5394e9..2f3baa5f6e9c940e385de2fb1430a5ce08d6d4d2 100644 (file)
@@ -8535,19 +8535,6 @@ static int rtl8152_system_resume(struct r8152 *tp)
                usb_submit_urb(tp->intr_urb, GFP_NOIO);
        }
 
-       /* If the device is RTL8152_INACCESSIBLE here then we should do a
-        * reset. This is important because the usb_lock_device_for_reset()
-        * that happens as a result of usb_queue_reset_device() will silently
-        * fail if the device was suspended or if too much time passed.
-        *
-        * NOTE: The device is locked here so we can directly do the reset.
-        * We don't need usb_lock_device_for_reset() because that's just a
-        * wrapper over device_lock() and device_resume() (which calls us)
-        * does that for us.
-        */
-       if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
-               usb_reset_device(tp->udev);
-
        return 0;
 }
 
@@ -8658,19 +8645,33 @@ static int rtl8152_suspend(struct usb_interface *intf, pm_message_t message)
 static int rtl8152_resume(struct usb_interface *intf)
 {
        struct r8152 *tp = usb_get_intfdata(intf);
+       bool runtime_resume = test_bit(SELECTIVE_SUSPEND, &tp->flags);
        int ret;
 
        mutex_lock(&tp->control);
 
        rtl_reset_ocp_base(tp);
 
-       if (test_bit(SELECTIVE_SUSPEND, &tp->flags))
+       if (runtime_resume)
                ret = rtl8152_runtime_resume(tp);
        else
                ret = rtl8152_system_resume(tp);
 
        mutex_unlock(&tp->control);
 
+       /* If the device is RTL8152_INACCESSIBLE here then we should do a
+        * reset. This is important because the usb_lock_device_for_reset()
+        * that happens as a result of usb_queue_reset_device() will silently
+        * fail if the device was suspended or if too much time passed.
+        *
+        * NOTE: The device is locked here so we can directly do the reset.
+        * We don't need usb_lock_device_for_reset() because that's just a
+        * wrapper over device_lock() and device_resume() (which calls us)
+        * does that for us.
+        */
+       if (!runtime_resume && test_bit(RTL8152_INACCESSIBLE, &tp->flags))
+               usb_reset_device(tp->udev);
+
        return ret;
 }