USB: replace flush_workqueue with cancel_sync_work
authorAlan Stern <stern@rowland.harvard.edu>
Tue, 29 May 2007 20:34:52 +0000 (16:34 -0400)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Tue, 29 May 2007 20:39:07 +0000 (13:39 -0700)
commitd5d4db704b962773c03ee3beb3258b6450611e66
treefc0ffd83dff3a4bd19a33ba6c2af73cfd4de7da4
parentc420bc9f09a0926b708c3edb27eacba434a4f4ba
USB: replace flush_workqueue with cancel_sync_work

This patch (as912) replaces a couple of calls to flush_workqueue()
with cancel_sync_work() and cancel_rearming_delayed_work().  Using a
more directed approach allows us to avoid some nasty deadlocks.  The
prime example occurs when a first-level device (the parent is a root
hub) is removed while at the same time the root hub gets a remote
wakeup request.  khubd would try to flush the autosuspend workqueue
while holding the root-hub's lock, and the remote-wakeup workqueue
routine would be waiting to lock the root hub.

The patch also reorganizes the power management portion of
usb_disconnect(), separating it out into its own routine.  The
autosuspend workqueue entry is cancelled immediately instead of
waiting for the device's release routine.  In addition,
synchronization with the autosuspend thread is carried out even for
root hubs (an oversight in the original code).

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Greg KH <gregkh@suse.de>
Cc: Mark Lord <lkml@rtr.ca>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
drivers/usb/core/hcd.c
drivers/usb/core/hub.c
drivers/usb/core/usb.c