aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/storage/usb.c
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@pobox.com>2005-09-14 08:19:08 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-09-14 08:19:08 -0400
commit905ec87e93bc9e01b15c60035cd6a50c636cbaef (patch)
tree46fd7618d6511611ffc19eb0dd4d7bc6b90a41c2 /drivers/usb/storage/usb.c
parent1d6ae775d7a948c9575658eb41184fd2e506c0df (diff)
parent2f4ba45a75d6383b4a1201169a808ffea416ffa0 (diff)
Merge /spare/repo/linux-2.6/
Diffstat (limited to 'drivers/usb/storage/usb.c')
-rw-r--r--drivers/usb/storage/usb.c90
1 files changed, 59 insertions, 31 deletions
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 77e7fc258aa2..f9a9bfa1aef5 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -90,7 +90,9 @@
90#ifdef CONFIG_USB_STORAGE_JUMPSHOT 90#ifdef CONFIG_USB_STORAGE_JUMPSHOT
91#include "jumpshot.h" 91#include "jumpshot.h"
92#endif 92#endif
93 93#ifdef CONFIG_USB_STORAGE_ONETOUCH
94#include "onetouch.h"
95#endif
94 96
95/* Some informational data */ 97/* Some informational data */
96MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>"); 98MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>");
@@ -390,11 +392,16 @@ SkipForAbort:
390 /* If an abort request was received we need to signal that 392 /* If an abort request was received we need to signal that
391 * the abort has finished. The proper test for this is 393 * the abort has finished. The proper test for this is
392 * the TIMED_OUT flag, not srb->result == DID_ABORT, because 394 * the TIMED_OUT flag, not srb->result == DID_ABORT, because
393 * a timeout/abort request might be received after all the 395 * the timeout might have occurred after the command had
394 * USB processing was complete. */ 396 * already completed with a different result code. */
395 if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) 397 if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {
396 complete(&(us->notify)); 398 complete(&(us->notify));
397 399
400 /* Allow USB transfers to resume */
401 clear_bit(US_FLIDX_ABORTING, &us->flags);
402 clear_bit(US_FLIDX_TIMED_OUT, &us->flags);
403 }
404
398 /* finished working on this command */ 405 /* finished working on this command */
399 us->srb = NULL; 406 us->srb = NULL;
400 scsi_unlock(host); 407 scsi_unlock(host);
@@ -786,6 +793,7 @@ static void usb_stor_release_resources(struct us_data *us)
786 * any more commands. 793 * any more commands.
787 */ 794 */
788 US_DEBUGP("-- sending exit command to thread\n"); 795 US_DEBUGP("-- sending exit command to thread\n");
796 set_bit(US_FLIDX_DISCONNECTING, &us->flags);
789 up(&us->sema); 797 up(&us->sema);
790 798
791 /* Call the destructor routine, if it exists */ 799 /* Call the destructor routine, if it exists */
@@ -816,6 +824,49 @@ static void dissociate_dev(struct us_data *us)
816 usb_set_intfdata(us->pusb_intf, NULL); 824 usb_set_intfdata(us->pusb_intf, NULL);
817} 825}
818 826
827/* First stage of disconnect processing: stop all commands and remove
828 * the host */
829static void quiesce_and_remove_host(struct us_data *us)
830{
831 /* Prevent new USB transfers, stop the current command, and
832 * interrupt a SCSI-scan or device-reset delay */
833 set_bit(US_FLIDX_DISCONNECTING, &us->flags);
834 usb_stor_stop_transport(us);
835 wake_up(&us->delay_wait);
836
837 /* It doesn't matter if the SCSI-scanning thread is still running.
838 * The thread will exit when it sees the DISCONNECTING flag. */
839
840 /* Wait for the current command to finish, then remove the host */
841 down(&us->dev_semaphore);
842 up(&us->dev_semaphore);
843
844 /* queuecommand won't accept any new commands and the control
845 * thread won't execute a previously-queued command. If there
846 * is such a command pending, complete it with an error. */
847 if (us->srb) {
848 us->srb->result = DID_NO_CONNECT << 16;
849 scsi_lock(us_to_host(us));
850 us->srb->scsi_done(us->srb);
851 us->srb = NULL;
852 scsi_unlock(us_to_host(us));
853 }
854
855 /* Now we own no commands so it's safe to remove the SCSI host */
856 scsi_remove_host(us_to_host(us));
857}
858
859/* Second stage of disconnect processing: deallocate all resources */
860static void release_everything(struct us_data *us)
861{
862 usb_stor_release_resources(us);
863 dissociate_dev(us);
864
865 /* Drop our reference to the host; the SCSI core will free it
866 * (and "us" along with it) when the refcount becomes 0. */
867 scsi_host_put(us_to_host(us));
868}
869
819/* Thread to carry out delayed SCSI-device scanning */ 870/* Thread to carry out delayed SCSI-device scanning */
820static int usb_stor_scan_thread(void * __us) 871static int usb_stor_scan_thread(void * __us)
821{ 872{
@@ -956,7 +1007,7 @@ static int storage_probe(struct usb_interface *intf,
956 if (result < 0) { 1007 if (result < 0) {
957 printk(KERN_WARNING USB_STORAGE 1008 printk(KERN_WARNING USB_STORAGE
958 "Unable to start the device-scanning thread\n"); 1009 "Unable to start the device-scanning thread\n");
959 scsi_remove_host(host); 1010 quiesce_and_remove_host(us);
960 goto BadDevice; 1011 goto BadDevice;
961 } 1012 }
962 atomic_inc(&total_threads); 1013 atomic_inc(&total_threads);
@@ -969,10 +1020,7 @@ static int storage_probe(struct usb_interface *intf,
969 /* We come here if there are any problems */ 1020 /* We come here if there are any problems */
970BadDevice: 1021BadDevice:
971 US_DEBUGP("storage_probe() failed\n"); 1022 US_DEBUGP("storage_probe() failed\n");
972 set_bit(US_FLIDX_DISCONNECTING, &us->flags); 1023 release_everything(us);
973 usb_stor_release_resources(us);
974 dissociate_dev(us);
975 scsi_host_put(host);
976 return result; 1024 return result;
977} 1025}
978 1026
@@ -982,28 +1030,8 @@ static void storage_disconnect(struct usb_interface *intf)
982 struct us_data *us = usb_get_intfdata(intf); 1030 struct us_data *us = usb_get_intfdata(intf);
983 1031
984 US_DEBUGP("storage_disconnect() called\n"); 1032 US_DEBUGP("storage_disconnect() called\n");
985 1033 quiesce_and_remove_host(us);
986 /* Prevent new USB transfers, stop the current command, and 1034 release_everything(us);
987 * interrupt a SCSI-scan or device-reset delay */
988 set_bit(US_FLIDX_DISCONNECTING, &us->flags);
989 usb_stor_stop_transport(us);
990 wake_up(&us->delay_wait);
991
992 /* It doesn't matter if the SCSI-scanning thread is still running.
993 * The thread will exit when it sees the DISCONNECTING flag. */
994
995 /* Wait for the current command to finish, then remove the host */
996 down(&us->dev_semaphore);
997 up(&us->dev_semaphore);
998 scsi_remove_host(us_to_host(us));
999
1000 /* Wait for everything to become idle and release all our resources */
1001 usb_stor_release_resources(us);
1002 dissociate_dev(us);
1003
1004 /* Drop our reference to the host; the SCSI core will free it
1005 * (and "us" along with it) when the refcount becomes 0. */
1006 scsi_host_put(us_to_host(us));
1007} 1035}
1008 1036
1009/*********************************************************************** 1037/***********************************************************************