aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/storage/usb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/storage/usb.c')
-rw-r--r--drivers/usb/storage/usb.c77
1 files changed, 36 insertions, 41 deletions
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 6b14f8d253f1..6bfd99dd57aa 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -320,16 +320,17 @@ static int usb_stor_control_thread(void * __us)
320 /* lock the device pointers */ 320 /* lock the device pointers */
321 mutex_lock(&(us->dev_mutex)); 321 mutex_lock(&(us->dev_mutex));
322 322
323 /* if the device has disconnected, we are free to exit */ 323 /* lock access to the state */
324 if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) { 324 scsi_lock(host);
325 US_DEBUGP("-- exiting\n"); 325
326 /* When we are called with no command pending, we're done */
327 if (us->srb == NULL) {
328 scsi_unlock(host);
326 mutex_unlock(&us->dev_mutex); 329 mutex_unlock(&us->dev_mutex);
330 US_DEBUGP("-- exiting\n");
327 break; 331 break;
328 } 332 }
329 333
330 /* lock access to the state */
331 scsi_lock(host);
332
333 /* has the command timed out *already* ? */ 334 /* has the command timed out *already* ? */
334 if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) { 335 if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
335 us->srb->result = DID_ABORT << 16; 336 us->srb->result = DID_ABORT << 16;
@@ -384,12 +385,8 @@ static int usb_stor_control_thread(void * __us)
384 /* lock access to the state */ 385 /* lock access to the state */
385 scsi_lock(host); 386 scsi_lock(host);
386 387
387 /* did the command already complete because of a disconnect? */
388 if (!us->srb)
389 ; /* nothing to do */
390
391 /* indicate that the command is done */ 388 /* indicate that the command is done */
392 else if (us->srb->result != DID_ABORT << 16) { 389 if (us->srb->result != DID_ABORT << 16) {
393 US_DEBUGP("scsi cmd done, result=0x%x\n", 390 US_DEBUGP("scsi cmd done, result=0x%x\n",
394 us->srb->result); 391 us->srb->result);
395 us->srb->scsi_done(us->srb); 392 us->srb->scsi_done(us->srb);
@@ -820,11 +817,10 @@ static void usb_stor_release_resources(struct us_data *us)
820 US_DEBUGP("-- %s\n", __func__); 817 US_DEBUGP("-- %s\n", __func__);
821 818
822 /* Tell the control thread to exit. The SCSI host must 819 /* Tell the control thread to exit. The SCSI host must
823 * already have been removed so it won't try to queue 820 * already have been removed and the DISCONNECTING flag set
824 * any more commands. 821 * so that we won't accept any more commands.
825 */ 822 */
826 US_DEBUGP("-- sending exit command to thread\n"); 823 US_DEBUGP("-- sending exit command to thread\n");
827 set_bit(US_FLIDX_DISCONNECTING, &us->dflags);
828 complete(&us->cmnd_ready); 824 complete(&us->cmnd_ready);
829 if (us->ctl_thread) 825 if (us->ctl_thread)
830 kthread_stop(us->ctl_thread); 826 kthread_stop(us->ctl_thread);
@@ -859,39 +855,36 @@ static void dissociate_dev(struct us_data *us)
859 usb_set_intfdata(us->pusb_intf, NULL); 855 usb_set_intfdata(us->pusb_intf, NULL);
860} 856}
861 857
862/* First stage of disconnect processing: stop all commands and remove 858/* First stage of disconnect processing: stop SCSI scanning,
863 * the host */ 859 * remove the host, and stop accepting new commands
860 */
864static void quiesce_and_remove_host(struct us_data *us) 861static void quiesce_and_remove_host(struct us_data *us)
865{ 862{
866 struct Scsi_Host *host = us_to_host(us); 863 struct Scsi_Host *host = us_to_host(us);
867 864
868 /* Prevent new USB transfers, stop the current command, and 865 /* If the device is really gone, cut short reset delays */
869 * interrupt a SCSI-scan or device-reset delay */ 866 if (us->pusb_dev->state == USB_STATE_NOTATTACHED)
870 scsi_lock(host); 867 set_bit(US_FLIDX_DISCONNECTING, &us->dflags);
871 set_bit(US_FLIDX_DISCONNECTING, &us->dflags);
872 scsi_unlock(host);
873 usb_stor_stop_transport(us);
874 wake_up(&us->delay_wait);
875 868
876 /* queuecommand won't accept any new commands and the control 869 /* Prevent SCSI-scanning (if it hasn't started yet)
877 * thread won't execute a previously-queued command. If there 870 * and wait for the SCSI-scanning thread to stop.
878 * is such a command pending, complete it with an error. */ 871 */
879 mutex_lock(&us->dev_mutex); 872 set_bit(US_FLIDX_DONT_SCAN, &us->dflags);
880 if (us->srb) { 873 wake_up(&us->delay_wait);
881 us->srb->result = DID_NO_CONNECT << 16; 874 wait_for_completion(&us->scanning_done);
882 scsi_lock(host);
883 us->srb->scsi_done(us->srb);
884 us->srb = NULL;
885 complete(&us->notify); /* in case of an abort */
886 scsi_unlock(host);
887 }
888 mutex_unlock(&us->dev_mutex);
889 875
890 /* Now we own no commands so it's safe to remove the SCSI host */ 876 /* Removing the host will perform an orderly shutdown: caches
877 * synchronized, disks spun down, etc.
878 */
891 scsi_remove_host(host); 879 scsi_remove_host(host);
892 880
893 /* Wait for the SCSI-scanning thread to stop */ 881 /* Prevent any new commands from being accepted and cut short
894 wait_for_completion(&us->scanning_done); 882 * reset delays.
883 */
884 scsi_lock(host);
885 set_bit(US_FLIDX_DISCONNECTING, &us->dflags);
886 scsi_unlock(host);
887 wake_up(&us->delay_wait);
895} 888}
896 889
897/* Second stage of disconnect processing: deallocate all resources */ 890/* Second stage of disconnect processing: deallocate all resources */
@@ -919,12 +912,12 @@ static int usb_stor_scan_thread(void * __us)
919 printk(KERN_DEBUG "usb-storage: waiting for device " 912 printk(KERN_DEBUG "usb-storage: waiting for device "
920 "to settle before scanning\n"); 913 "to settle before scanning\n");
921 wait_event_freezable_timeout(us->delay_wait, 914 wait_event_freezable_timeout(us->delay_wait,
922 test_bit(US_FLIDX_DISCONNECTING, &us->dflags), 915 test_bit(US_FLIDX_DONT_SCAN, &us->dflags),
923 delay_use * HZ); 916 delay_use * HZ);
924 } 917 }
925 918
926 /* If the device is still connected, perform the scanning */ 919 /* If the device is still connected, perform the scanning */
927 if (!test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) { 920 if (!test_bit(US_FLIDX_DONT_SCAN, &us->dflags)) {
928 921
929 /* For bulk-only devices, determine the max LUN value */ 922 /* For bulk-only devices, determine the max LUN value */
930 if (us->protocol == US_PR_BULK && 923 if (us->protocol == US_PR_BULK &&
@@ -1023,6 +1016,7 @@ static int storage_probe(struct usb_interface *intf,
1023 if (IS_ERR(th)) { 1016 if (IS_ERR(th)) {
1024 printk(KERN_WARNING USB_STORAGE 1017 printk(KERN_WARNING USB_STORAGE
1025 "Unable to start the device-scanning thread\n"); 1018 "Unable to start the device-scanning thread\n");
1019 complete(&us->scanning_done);
1026 quiesce_and_remove_host(us); 1020 quiesce_and_remove_host(us);
1027 result = PTR_ERR(th); 1021 result = PTR_ERR(th);
1028 goto BadDevice; 1022 goto BadDevice;
@@ -1065,6 +1059,7 @@ static struct usb_driver usb_storage_driver = {
1065 .pre_reset = storage_pre_reset, 1059 .pre_reset = storage_pre_reset,
1066 .post_reset = storage_post_reset, 1060 .post_reset = storage_post_reset,
1067 .id_table = storage_usb_ids, 1061 .id_table = storage_usb_ids,
1062 .soft_unbind = 1,
1068}; 1063};
1069 1064
1070static int __init usb_stor_init(void) 1065static int __init usb_stor_init(void)