Commit 0f138bbf authored by David Brownell's avatar David Brownell Committed by Greg Kroah-Hartman

[PATCH] USB: usbnet, prevent exotic rtnl deadlock

Turns out that when PM is in use, some D3cold resume paths
could have one thread, holding the network lock, deadlock
in flush_scheduled_work() since an event task is waiting
for that same lock.  Fix is to call that later, when the
lock isn't held.
parent efaa6ef9
...@@ -2048,8 +2048,11 @@ static int usbnet_stop (struct net_device *net) ...@@ -2048,8 +2048,11 @@ static int usbnet_stop (struct net_device *net)
dev->wait = 0; dev->wait = 0;
remove_wait_queue (&unlink_wakeup, &wait); remove_wait_queue (&unlink_wakeup, &wait);
// deferred work (task, timer, softirq) must also stop /* deferred work (task, timer, softirq) must also stop.
flush_scheduled_work (); * can't flush_scheduled_work() until we drop rtnl (later),
* else workers could deadlock; so make workers a NOP.
*/
dev->flags = 0;
del_timer_sync (&dev->delay); del_timer_sync (&dev->delay);
tasklet_kill (&dev->bh); tasklet_kill (&dev->bh);
...@@ -2488,6 +2491,9 @@ static void usbnet_disconnect (struct usb_interface *intf) ...@@ -2488,6 +2491,9 @@ static void usbnet_disconnect (struct usb_interface *intf)
unregister_netdev (dev->net); unregister_netdev (dev->net);
/* we don't hold rtnl here ... */
flush_scheduled_work ();
if (dev->driver_info->unbind) if (dev->driver_info->unbind)
dev->driver_info->unbind (dev, intf); dev->driver_info->unbind (dev, intf);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment