summaryrefslogtreecommitdiff
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 @@
#include <linux/slab.h>
#include <linux/kthread.h>
#include <linux/mutex.h>
+#include <linux/utsrelease.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
@@ -373,8 +374,12 @@ static int usb_stor_control_thread(void * __us)
/* lock access to the state */
scsi_lock(host);
+ /* did the command already complete because of a disconnect? */
+ if (!us->srb)
+ ; /* nothing to do */
+
/* indicate that the command is done */
- if (us->srb->result != DID_ABORT << 16) {
+ else if (us->srb->result != DID_ABORT << 16) {
US_DEBUGP("scsi cmd done, result=0x%x\n",
us->srb->result);
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)
if (msg >= 0 && !(us->flags & US_FL_NEED_OVERRIDE))
printk(KERN_NOTICE USB_STORAGE "This device "
"(%04x,%04x,%04x S %02x P %02x)"
- " has %s in unusual_devs.h\n"
+ " has %s in unusual_devs.h (kernel"
+ " %s)\n"
" Please send a copy of this message to "
"<linux-usb-devel@lists.sourceforge.net>\n",
le16_to_cpu(ddesc->idVendor),
@@ -532,7 +538,8 @@ static void get_device_info(struct us_data *us, const struct usb_device_id *id)
le16_to_cpu(ddesc->bcdDevice),
idesc->bInterfaceSubClass,
idesc->bInterfaceProtocol,
- msgs[msg]);
+ msgs[msg],
+ UTS_RELEASE);
}
}
@@ -836,32 +843,34 @@ static void dissociate_dev(struct us_data *us)
* the host */
static void quiesce_and_remove_host(struct us_data *us)
{
+ struct Scsi_Host *host = us_to_host(us);
+
/* Prevent new USB transfers, stop the current command, and
* interrupt a SCSI-scan or device-reset delay */
+ scsi_lock(host);
set_bit(US_FLIDX_DISCONNECTING, &us->flags);
+ scsi_unlock(host);
usb_stor_stop_transport(us);
wake_up(&us->delay_wait);
/* It doesn't matter if the SCSI-scanning thread is still running.
* The thread will exit when it sees the DISCONNECTING flag. */
- /* Wait for the current command to finish, then remove the host */
- mutex_lock(&us->dev_mutex);
- mutex_unlock(&us->dev_mutex);
-
/* queuecommand won't accept any new commands and the control
* thread won't execute a previously-queued command. If there
* is such a command pending, complete it with an error. */
+ mutex_lock(&us->dev_mutex);
if (us->srb) {
us->srb->result = DID_NO_CONNECT << 16;
- scsi_lock(us_to_host(us));
+ scsi_lock(host);
us->srb->scsi_done(us->srb);
us->srb = NULL;
- scsi_unlock(us_to_host(us));
+ scsi_unlock(host);
}
+ mutex_unlock(&us->dev_mutex);
/* Now we own no commands so it's safe to remove the SCSI host */
- scsi_remove_host(us_to_host(us));
+ scsi_remove_host(host);
}
/* Second stage of disconnect processing: deallocate all resources */