Skip to content

Commit f9e1b7a

Browse files
sergey-senozhatskyNipaLocal
authored andcommitted
net: usb: r8152: resume-reset deadlock
I'm looking into the following deadlock <4>[ 1596.492101] schedule_preempt_disabled+0x15/0x30 <4>[ 1596.492170] __mutex_lock_common+0x256/0x490 <4>[ 1596.492209] __mutex_lock_slowpath+0x18/0x30 <4>[ 1596.492249] __rtl8152_set_mac_address+0x80/0x1f0 [r8152 (HASH:ce6f 4)] <4>[ 1596.492327] dev_set_mac_address+0x7d/0x150 <4>[ 1596.492395] rtl8152_post_reset+0x72/0x150 [r8152 (HASH:ce6f 4)] <4>[ 1596.492438] usb_reset_device+0x1ce/0x220 <4>[ 1596.492507] rtl8152_resume+0x99/0xc0 [r8152 (HASH:ce6f 4)] <4>[ 1596.492550] usb_resume_interface+0x3c/0xc0 <4>[ 1596.492619] usb_resume_both+0x104/0x150 <4>[ 1596.492657] ? usb_dev_suspend+0x20/0x20 <4>[ 1596.492725] usb_resume+0x22/0x110 <4>[ 1596.492763] ? usb_dev_suspend+0x20/0x20 <4>[ 1596.492800] dpm_run_callback+0x83/0x1d0 <4>[ 1596.492873] device_resume+0x35f/0x3d0 <4>[ 1596.492912] ? pm_verb+0xa0/0xa0 <4>[ 1596.492951] async_resume+0x1d/0x30 <4>[ 1596.493019] async_run_entry_fn+0x2b/0xd0 <4>[ 1596.493060] worker_thread+0x2ce/0xef0 <4>[ 1596.493101] ? cancel_delayed_work+0x2d0/0x2d0 <4>[ 1596.493170] kthread+0x16d/0x190 <4>[ 1596.493209] ? cancel_delayed_work+0x2d0/0x2d0 <4>[ 1596.493247] ? kthread_associate_blkcg+0x80/0x80 <4>[ 1596.493316] ret_from_fork+0x1f/0x30 rtl8152_resume() seems to be tricky, because it's under tp->control mutex, when it can see RTL8152_INACCESSIBLE and initiate a full device reset via usb_reset_device(), which eventually re-enters rtl8152, at which point it calls __rtl8152_set_mac_address() and deadlocks on tp->control (I assume) mutex. __rtl8152_set_mac_address() has in_resume flag (added by Takashi in 776ac63), which is set only in "reset_resume" case, wheres what we have is "resume_reset". Moreover in_resume flag is not for tp->control mutex, as far as I can tell, but for PM lock. When we set_mac_address from resume_reset, we lose in_resume flat, so not only we deadlock on tp->control mutex, but also we may (I guess) deadlock on the PM lock. Also, we still call rtl8152_resume() even in reset_resume, which I assume still can end up resetting device and hence in set_mac_address() in non-in_resume mode, potentially triggering the same deadlock that Takashi fixed. Well, unless I'm missing something. So I don't think I want to add another flag to mark "current owns tp->control mutex" so that we can handle re-entry. How about moving usb reset outside of tp->control scope? Is there any harm in doing that? Signed-off-by: NipaLocal <nipa@local>
1 parent c02693f commit f9e1b7a

File tree

1 file changed

+13
-13
lines changed

1 file changed

+13
-13
lines changed

drivers/net/usb/r8152.c

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8535,19 +8535,6 @@ static int rtl8152_system_resume(struct r8152 *tp)
85358535
usb_submit_urb(tp->intr_urb, GFP_NOIO);
85368536
}
85378537

8538-
/* If the device is RTL8152_INACCESSIBLE here then we should do a
8539-
* reset. This is important because the usb_lock_device_for_reset()
8540-
* that happens as a result of usb_queue_reset_device() will silently
8541-
* fail if the device was suspended or if too much time passed.
8542-
*
8543-
* NOTE: The device is locked here so we can directly do the reset.
8544-
* We don't need usb_lock_device_for_reset() because that's just a
8545-
* wrapper over device_lock() and device_resume() (which calls us)
8546-
* does that for us.
8547-
*/
8548-
if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
8549-
usb_reset_device(tp->udev);
8550-
85518538
return 0;
85528539
}
85538540

@@ -8671,6 +8658,19 @@ static int rtl8152_resume(struct usb_interface *intf)
86718658

86728659
mutex_unlock(&tp->control);
86738660

8661+
/* If the device is RTL8152_INACCESSIBLE here then we should do a
8662+
* reset. This is important because the usb_lock_device_for_reset()
8663+
* that happens as a result of usb_queue_reset_device() will silently
8664+
* fail if the device was suspended or if too much time passed.
8665+
*
8666+
* NOTE: The device is locked here so we can directly do the reset.
8667+
* We don't need usb_lock_device_for_reset() because that's just a
8668+
* wrapper over device_lock() and device_resume() (which calls us)
8669+
* does that for us.
8670+
*/
8671+
if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
8672+
usb_reset_device(tp->udev);
8673+
86748674
return ret;
86758675
}
86768676

0 commit comments

Comments
 (0)