diff options
Diffstat (limited to 'drivers/usb/storage/usb.c')
| -rw-r--r-- | drivers/usb/storage/usb.c | 33 |
1 files changed, 6 insertions, 27 deletions
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 28842d208bb0..25e557d4fe6b 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); | |||
| 112 | MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device"); | 112 | MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device"); |
| 113 | 113 | ||
| 114 | 114 | ||
| 115 | /* These are used to make sure the module doesn't unload before all the | ||
| 116 | * threads have exited. | ||
| 117 | */ | ||
| 118 | static atomic_t total_threads = ATOMIC_INIT(0); | ||
| 119 | static DECLARE_COMPLETION(threads_gone); | ||
| 120 | |||
| 121 | |||
| 122 | /* | 115 | /* |
| 123 | * The entries in this table correspond, line for line, | 116 | * The entries in this table correspond, line for line, |
| 124 | * with the entries of us_unusual_dev_list[]. | 117 | * with the entries of us_unusual_dev_list[]. |
| @@ -879,9 +872,6 @@ static void quiesce_and_remove_host(struct us_data *us) | |||
| 879 | usb_stor_stop_transport(us); | 872 | usb_stor_stop_transport(us); |
| 880 | wake_up(&us->delay_wait); | 873 | wake_up(&us->delay_wait); |
| 881 | 874 | ||
| 882 | /* It doesn't matter if the SCSI-scanning thread is still running. | ||
| 883 | * The thread will exit when it sees the DISCONNECTING flag. */ | ||
| 884 | |||
| 885 | /* queuecommand won't accept any new commands and the control | 875 | /* queuecommand won't accept any new commands and the control |
| 886 | * thread won't execute a previously-queued command. If there | 876 | * thread won't execute a previously-queued command. If there |
| 887 | * is such a command pending, complete it with an error. */ | 877 | * is such a command pending, complete it with an error. */ |
| @@ -891,12 +881,16 @@ static void quiesce_and_remove_host(struct us_data *us) | |||
| 891 | scsi_lock(host); | 881 | scsi_lock(host); |
| 892 | us->srb->scsi_done(us->srb); | 882 | us->srb->scsi_done(us->srb); |
| 893 | us->srb = NULL; | 883 | us->srb = NULL; |
| 884 | complete(&us->notify); /* in case of an abort */ | ||
| 894 | scsi_unlock(host); | 885 | scsi_unlock(host); |
| 895 | } | 886 | } |
| 896 | mutex_unlock(&us->dev_mutex); | 887 | mutex_unlock(&us->dev_mutex); |
| 897 | 888 | ||
| 898 | /* Now we own no commands so it's safe to remove the SCSI host */ | 889 | /* Now we own no commands so it's safe to remove the SCSI host */ |
| 899 | scsi_remove_host(host); | 890 | scsi_remove_host(host); |
| 891 | |||
| 892 | /* Wait for the SCSI-scanning thread to stop */ | ||
| 893 | wait_for_completion(&us->scanning_done); | ||
| 900 | } | 894 | } |
| 901 | 895 | ||
| 902 | /* Second stage of disconnect processing: deallocate all resources */ | 896 | /* Second stage of disconnect processing: deallocate all resources */ |
| @@ -947,9 +941,8 @@ retry: | |||
| 947 | /* Should we unbind if no devices were detected? */ | 941 | /* Should we unbind if no devices were detected? */ |
| 948 | } | 942 | } |
| 949 | 943 | ||
| 950 | scsi_host_put(us_to_host(us)); | ||
| 951 | usb_autopm_put_interface(us->pusb_intf); | 944 | usb_autopm_put_interface(us->pusb_intf); |
| 952 | complete_and_exit(&threads_gone, 0); | 945 | complete_and_exit(&us->scanning_done, 0); |
| 953 | } | 946 | } |
| 954 | 947 | ||
| 955 | 948 | ||
| @@ -984,6 +977,7 @@ static int storage_probe(struct usb_interface *intf, | |||
| 984 | init_MUTEX_LOCKED(&(us->sema)); | 977 | init_MUTEX_LOCKED(&(us->sema)); |
| 985 | init_completion(&(us->notify)); | 978 | init_completion(&(us->notify)); |
| 986 | init_waitqueue_head(&us->delay_wait); | 979 | init_waitqueue_head(&us->delay_wait); |
| 980 | init_completion(&us->scanning_done); | ||
| 987 | 981 | ||
| 988 | /* Associate the us_data structure with the USB device */ | 982 | /* Associate the us_data structure with the USB device */ |
| 989 | result = associate_dev(us, intf); | 983 | result = associate_dev(us, intf); |
| @@ -1033,11 +1027,6 @@ static int storage_probe(struct usb_interface *intf, | |||
| 1033 | goto BadDevice; | 1027 | goto BadDevice; |
| 1034 | } | 1028 | } |
| 1035 | 1029 | ||
| 1036 | /* Take a reference to the host for the scanning thread and | ||
| 1037 | * count it among all the threads we have launched. Then | ||
| 1038 | * start it up. */ | ||
| 1039 | scsi_host_get(us_to_host(us)); | ||
| 1040 | atomic_inc(&total_threads); | ||
| 1041 | usb_autopm_get_interface(intf); /* dropped in the scanning thread */ | 1030 | usb_autopm_get_interface(intf); /* dropped in the scanning thread */ |
| 1042 | wake_up_process(th); | 1031 | wake_up_process(th); |
| 1043 | 1032 | ||
| @@ -1104,16 +1093,6 @@ static void __exit usb_stor_exit(void) | |||
| 1104 | US_DEBUGP("-- calling usb_deregister()\n"); | 1093 | US_DEBUGP("-- calling usb_deregister()\n"); |
| 1105 | usb_deregister(&usb_storage_driver) ; | 1094 | usb_deregister(&usb_storage_driver) ; |
| 1106 | 1095 | ||
| 1107 | /* Don't return until all of our control and scanning threads | ||
| 1108 | * have exited. Since each thread signals threads_gone as its | ||
| 1109 | * last act, we have to call wait_for_completion the right number | ||
| 1110 | * of times. | ||
| 1111 | */ | ||
| 1112 | while (atomic_read(&total_threads) > 0) { | ||
| 1113 | wait_for_completion(&threads_gone); | ||
| 1114 | atomic_dec(&total_threads); | ||
| 1115 | } | ||
| 1116 | |||
| 1117 | usb_usual_clear_present(USB_US_TYPE_STOR); | 1096 | usb_usual_clear_present(USB_US_TYPE_STOR); |
| 1118 | } | 1097 | } |
| 1119 | 1098 | ||
