ChangeSet 1.1119.1.11, 2003/08/06 16:02:01-07:00, david-b@pacbell.net

[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.


 drivers/usb/net/usbnet.c |   10 ++++++++--
 1 files changed, 8 insertions(+), 2 deletions(-)


diff -Nru a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
--- a/drivers/usb/net/usbnet.c	Fri Aug  8 17:05:07 2003
+++ b/drivers/usb/net/usbnet.c	Fri Aug  8 17:05:07 2003
@@ -2048,8 +2048,11 @@
 	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);
 
@@ -2487,6 +2490,9 @@
 		dev->driver_info->description);
 	
 	unregister_netdev (dev->net);
+
+	/* we don't hold rtnl here ... */
+	flush_scheduled_work ();
 
 	if (dev->driver_info->unbind)
 		dev->driver_info->unbind (dev, intf);
