diff options
| author | Jeff Garzik <jgarzik@pobox.com> | 2005-09-14 08:19:08 -0400 |
|---|---|---|
| committer | Jeff Garzik <jgarzik@pobox.com> | 2005-09-14 08:19:08 -0400 |
| commit | 905ec87e93bc9e01b15c60035cd6a50c636cbaef (patch) | |
| tree | 46fd7618d6511611ffc19eb0dd4d7bc6b90a41c2 /drivers/usb/storage/usb.c | |
| parent | 1d6ae775d7a948c9575658eb41184fd2e506c0df (diff) | |
| parent | 2f4ba45a75d6383b4a1201169a808ffea416ffa0 (diff) | |
Merge /spare/repo/linux-2.6/
Diffstat (limited to 'drivers/usb/storage/usb.c')
| -rw-r--r-- | drivers/usb/storage/usb.c | 90 |
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 */ |
| 96 | MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>"); | 98 | MODULE_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 */ | ||
| 829 | static 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 */ | ||
| 860 | static 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 */ |
| 820 | static int usb_stor_scan_thread(void * __us) | 871 | static 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 */ |
| 970 | BadDevice: | 1021 | BadDevice: |
| 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 | /*********************************************************************** |
