aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/storage/usb.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-08-23 21:35:04 -0700
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-08-23 21:35:04 -0700
commit9e1a3e31cbfd5f5822e633c4bdf3304079cb10c2 (patch)
tree88653393c17c0ac5c0b30a244d6e6dc97b314e1f /drivers/usb/storage/usb.c
parentde80af4cc9c30318224b8520dc76a7d097e64cbd (diff)
parentd65cc1b45e7d3a24c25fd3d730042e407d6d64ce (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/usb-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/usb-2.6: (35 commits) usb: add PRODUCT, TYPE to usb-interface events USB: resubmission unusual_devs modification for Nikon D80 usb quirks: Add Canon EOS 5D (PC Connection mode) to the autosuspend blacklist USB: make EHCI initialize properly on PPC SOCs UEAGLE: Remove sysfs files on error case USB: fsl_usb2_udc: fix bug in processing setup requests USB: g_file_storage: fix bug in DMA buffer handling USB: update last_busy field correctly USB: fix DoS in pwc USB video driver USB: allow retry on descriptor fetch errors USB: unkill cxacru atm driver USB: Adding support for HTC Smartphones to ipaq USB: another quirky device USB: quirky mass storage device USB: ohci, fix oddball gcc warning usb-storage: fix bugs in the disconnect pathway usb: typo in usb R8A66597 HCD config USB: accept 1-byte Device Status replies, fixing some b0rken devices USB: blacklist Samsung ML-2010 printer usb-serial: fix oti6858.c segfault in termios handling ...
Diffstat (limited to 'drivers/usb/storage/usb.c')
-rw-r--r--drivers/usb/storage/usb.c33
1 files changed, 6 insertions, 27 deletions
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 28842d208bb..25e557d4fe6 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -112,13 +112,6 @@ module_param(delay_use, uint, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device");
-/* These are used to make sure the module doesn't unload before all the
- * threads have exited.
- */
-static atomic_t total_threads = ATOMIC_INIT(0);
-static DECLARE_COMPLETION(threads_gone);
-
-
/*
* The entries in this table correspond, line for line,
* with the entries of us_unusual_dev_list[].
@@ -879,9 +872,6 @@ static void quiesce_and_remove_host(struct us_data *us)
usb_stor_stop_transport(us);
wake_up(&us->delay_wait);
- /* It doesn't matter if the SCSI-scanning thread is still running.
- * The thread will exit when it sees the DISCONNECTING flag. */
-
/* queuecommand won't accept any new commands and the control
* thread won't execute a previously-queued command. If there
* is such a command pending, complete it with an error. */
@@ -891,12 +881,16 @@ static void quiesce_and_remove_host(struct us_data *us)
scsi_lock(host);
us->srb->scsi_done(us->srb);
us->srb = NULL;
+ complete(&us->notify); /* in case of an abort */
scsi_unlock(host);
}
mutex_unlock(&us->dev_mutex);
/* Now we own no commands so it's safe to remove the SCSI host */
scsi_remove_host(host);
+
+ /* Wait for the SCSI-scanning thread to stop */
+ wait_for_completion(&us->scanning_done);
}
/* Second stage of disconnect processing: deallocate all resources */
@@ -947,9 +941,8 @@ retry:
/* Should we unbind if no devices were detected? */
}
- scsi_host_put(us_to_host(us));
usb_autopm_put_interface(us->pusb_intf);
- complete_and_exit(&threads_gone, 0);
+ complete_and_exit(&us->scanning_done, 0);
}
@@ -984,6 +977,7 @@ static int storage_probe(struct usb_interface *intf,
init_MUTEX_LOCKED(&(us->sema));
init_completion(&(us->notify));
init_waitqueue_head(&us->delay_wait);
+ init_completion(&us->scanning_done);
/* Associate the us_data structure with the USB device */
result = associate_dev(us, intf);
@@ -1033,11 +1027,6 @@ static int storage_probe(struct usb_interface *intf,
goto BadDevice;
}
- /* Take a reference to the host for the scanning thread and
- * count it among all the threads we have launched. Then
- * start it up. */
- scsi_host_get(us_to_host(us));
- atomic_inc(&total_threads);
usb_autopm_get_interface(intf); /* dropped in the scanning thread */
wake_up_process(th);
@@ -1104,16 +1093,6 @@ static void __exit usb_stor_exit(void)
US_DEBUGP("-- calling usb_deregister()\n");
usb_deregister(&usb_storage_driver) ;
- /* Don't return until all of our control and scanning threads
- * have exited. Since each thread signals threads_gone as its
- * last act, we have to call wait_for_completion the right number
- * of times.
- */
- while (atomic_read(&total_threads) > 0) {
- wait_for_completion(&threads_gone);
- atomic_dec(&total_threads);
- }
-
usb_usual_clear_present(USB_US_TYPE_STOR);
}