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.c29
1 files changed, 19 insertions, 10 deletions
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 1185acac4b21..5ee19be52f65 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -55,6 +55,7 @@
55#include <linux/slab.h> 55#include <linux/slab.h>
56#include <linux/kthread.h> 56#include <linux/kthread.h>
57#include <linux/mutex.h> 57#include <linux/mutex.h>
58#include <linux/utsrelease.h>
58 59
59#include <scsi/scsi.h> 60#include <scsi/scsi.h>
60#include <scsi/scsi_cmnd.h> 61#include <scsi/scsi_cmnd.h>
@@ -373,8 +374,12 @@ static int usb_stor_control_thread(void * __us)
373 /* lock access to the state */ 374 /* lock access to the state */
374 scsi_lock(host); 375 scsi_lock(host);
375 376
377 /* did the command already complete because of a disconnect? */
378 if (!us->srb)
379 ; /* nothing to do */
380
376 /* indicate that the command is done */ 381 /* indicate that the command is done */
377 if (us->srb->result != DID_ABORT << 16) { 382 else if (us->srb->result != DID_ABORT << 16) {
378 US_DEBUGP("scsi cmd done, result=0x%x\n", 383 US_DEBUGP("scsi cmd done, result=0x%x\n",
379 us->srb->result); 384 us->srb->result);
380 us->srb->scsi_done(us->srb); 385 us->srb->scsi_done(us->srb);
@@ -524,7 +529,8 @@ static void get_device_info(struct us_data *us, const struct usb_device_id *id)
524 if (msg >= 0 && !(us->flags & US_FL_NEED_OVERRIDE)) 529 if (msg >= 0 && !(us->flags & US_FL_NEED_OVERRIDE))
525 printk(KERN_NOTICE USB_STORAGE "This device " 530 printk(KERN_NOTICE USB_STORAGE "This device "
526 "(%04x,%04x,%04x S %02x P %02x)" 531 "(%04x,%04x,%04x S %02x P %02x)"
527 " has %s in unusual_devs.h\n" 532 " has %s in unusual_devs.h (kernel"
533 " %s)\n"
528 " Please send a copy of this message to " 534 " Please send a copy of this message to "
529 "<linux-usb-devel@lists.sourceforge.net>\n", 535 "<linux-usb-devel@lists.sourceforge.net>\n",
530 le16_to_cpu(ddesc->idVendor), 536 le16_to_cpu(ddesc->idVendor),
@@ -532,7 +538,8 @@ static void get_device_info(struct us_data *us, const struct usb_device_id *id)
532 le16_to_cpu(ddesc->bcdDevice), 538 le16_to_cpu(ddesc->bcdDevice),
533 idesc->bInterfaceSubClass, 539 idesc->bInterfaceSubClass,
534 idesc->bInterfaceProtocol, 540 idesc->bInterfaceProtocol,
535 msgs[msg]); 541 msgs[msg],
542 UTS_RELEASE);
536 } 543 }
537} 544}
538 545
@@ -836,32 +843,34 @@ static void dissociate_dev(struct us_data *us)
836 * the host */ 843 * the host */
837static void quiesce_and_remove_host(struct us_data *us) 844static void quiesce_and_remove_host(struct us_data *us)
838{ 845{
846 struct Scsi_Host *host = us_to_host(us);
847
839 /* Prevent new USB transfers, stop the current command, and 848 /* Prevent new USB transfers, stop the current command, and
840 * interrupt a SCSI-scan or device-reset delay */ 849 * interrupt a SCSI-scan or device-reset delay */
850 scsi_lock(host);
841 set_bit(US_FLIDX_DISCONNECTING, &us->flags); 851 set_bit(US_FLIDX_DISCONNECTING, &us->flags);
852 scsi_unlock(host);
842 usb_stor_stop_transport(us); 853 usb_stor_stop_transport(us);
843 wake_up(&us->delay_wait); 854 wake_up(&us->delay_wait);
844 855
845 /* It doesn't matter if the SCSI-scanning thread is still running. 856 /* It doesn't matter if the SCSI-scanning thread is still running.
846 * The thread will exit when it sees the DISCONNECTING flag. */ 857 * The thread will exit when it sees the DISCONNECTING flag. */
847 858
848 /* Wait for the current command to finish, then remove the host */
849 mutex_lock(&us->dev_mutex);
850 mutex_unlock(&us->dev_mutex);
851
852 /* queuecommand won't accept any new commands and the control 859 /* queuecommand won't accept any new commands and the control
853 * thread won't execute a previously-queued command. If there 860 * thread won't execute a previously-queued command. If there
854 * is such a command pending, complete it with an error. */ 861 * is such a command pending, complete it with an error. */
862 mutex_lock(&us->dev_mutex);
855 if (us->srb) { 863 if (us->srb) {
856 us->srb->result = DID_NO_CONNECT << 16; 864 us->srb->result = DID_NO_CONNECT << 16;
857 scsi_lock(us_to_host(us)); 865 scsi_lock(host);
858 us->srb->scsi_done(us->srb); 866 us->srb->scsi_done(us->srb);
859 us->srb = NULL; 867 us->srb = NULL;
860 scsi_unlock(us_to_host(us)); 868 scsi_unlock(host);
861 } 869 }
870 mutex_unlock(&us->dev_mutex);
862 871
863 /* Now we own no commands so it's safe to remove the SCSI host */ 872 /* Now we own no commands so it's safe to remove the SCSI host */
864 scsi_remove_host(us_to_host(us)); 873 scsi_remove_host(host);
865} 874}
866 875
867/* Second stage of disconnect processing: deallocate all resources */ 876/* Second stage of disconnect processing: deallocate all resources */