]> git.hungrycats.org Git - linux/commitdiff
[PATCH] USB: usbnet, prevent exotic rtnl deadlock
authorDavid Brownell <david-b@pacbell.net>
Wed, 6 Aug 2003 09:02:01 +0000 (02:02 -0700)
committerGreg Kroah-Hartman <greg@kroah.com>
Wed, 6 Aug 2003 09:02:01 +0000 (02:02 -0700)
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.

drivers/usb/net/usbnet.c

index 80c1443494fff4b41e99b249c9bb3230db199b41..1249b514ed5ace37c85f51c4049344c92bef544f 100644 (file)
@@ -2048,8 +2048,11 @@ static int usbnet_stop (struct net_device *net)
        dev->wait = 0;
        remove_wait_queue (&unlink_wakeup, &wait); 
 
-       // deferred work (task, timer, softirq) must also stop
-       flush_scheduled_work ();
+       /* deferred work (task, timer, softirq) must also stop.
+        * 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);
        tasklet_kill (&dev->bh);
 
@@ -2488,6 +2491,9 @@ static void usbnet_disconnect (struct usb_interface *intf)
        
        unregister_netdev (dev->net);
 
+       /* we don't hold rtnl here ... */
+       flush_scheduled_work ();
+
        if (dev->driver_info->unbind)
                dev->driver_info->unbind (dev, intf);