aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/storage
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/storage')
-rw-r--r--drivers/usb/storage/scsiglue.c20
-rw-r--r--drivers/usb/storage/unusual_devs.h35
-rw-r--r--drivers/usb/storage/usb.c11
3 files changed, 52 insertions, 14 deletions
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index d34dc9f417f..4837524eada 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -227,42 +227,42 @@ static int queuecommand(struct scsi_cmnd *srb,
***********************************************************************/
/* Command timeout and abort */
-/* This is always called with scsi_lock(host) held */
static int command_abort(struct scsi_cmnd *srb)
{
struct us_data *us = host_to_us(srb->device->host);
US_DEBUGP("%s called\n", __FUNCTION__);
+ /* us->srb together with the TIMED_OUT, RESETTING, and ABORTING
+ * bits are protected by the host lock. */
+ scsi_lock(us_to_host(us));
+
/* Is this command still active? */
if (us->srb != srb) {
+ scsi_unlock(us_to_host(us));
US_DEBUGP ("-- nothing to abort\n");
return FAILED;
}
/* Set the TIMED_OUT bit. Also set the ABORTING bit, but only if
* a device reset isn't already in progress (to avoid interfering
- * with the reset). To prevent races with auto-reset, we must
- * stop any ongoing USB transfers while still holding the host
- * lock. */
+ * with the reset). Note that we must retain the host lock while
+ * calling usb_stor_stop_transport(); otherwise it might interfere
+ * with an auto-reset that begins as soon as we release the lock. */
set_bit(US_FLIDX_TIMED_OUT, &us->flags);
if (!test_bit(US_FLIDX_RESETTING, &us->flags)) {
set_bit(US_FLIDX_ABORTING, &us->flags);
usb_stor_stop_transport(us);
}
+ scsi_unlock(us_to_host(us));
/* Wait for the aborted command to finish */
wait_for_completion(&us->notify);
-
- /* Reacquire the lock and allow USB transfers to resume */
- clear_bit(US_FLIDX_ABORTING, &us->flags);
- clear_bit(US_FLIDX_TIMED_OUT, &us->flags);
return SUCCESS;
}
/* This invokes the transport reset mechanism to reset the state of the
* device */
-/* This is always called with scsi_lock(host) held */
static int device_reset(struct scsi_cmnd *srb)
{
struct us_data *us = host_to_us(srb->device->host);
@@ -279,7 +279,6 @@ static int device_reset(struct scsi_cmnd *srb)
}
/* Simulate a SCSI bus reset by resetting the device's USB port. */
-/* This is always called with scsi_lock(host) held */
static int bus_reset(struct scsi_cmnd *srb)
{
struct us_data *us = host_to_us(srb->device->host);
@@ -291,7 +290,6 @@ static int bus_reset(struct scsi_cmnd *srb)
result = usb_stor_port_reset(us);
up(&(us->dev_semaphore));
- /* lock the host for the return */
return result < 0 ? FAILED : SUCCESS;
}
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index ad0cfd7a782..b79dad1b598 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -86,6 +86,16 @@ UNUSUAL_DEV( 0x040d, 0x6205, 0x0003, 0x0003,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
+/* Reported by Sebastian Kapfer <sebastian_kapfer@gmx.net>
+ * and Olaf Hering <olh@suse.de> (different bcd's, same vendor/product)
+ * for USB floppies that need the SINGLE_LUN enforcement.
+ */
+UNUSUAL_DEV( 0x0409, 0x0040, 0x0000, 0x9999,
+ "NEC",
+ "NEC USB UF000x",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_SINGLE_LUN ),
+
/* Deduced by Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
* Entry needed for flags: US_FL_FIX_INQUIRY because initial inquiry message
* always fails and confuses drive.
@@ -96,6 +106,13 @@ UNUSUAL_DEV( 0x0411, 0x001c, 0x0113, 0x0113,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_INQUIRY ),
+/* Reported by Olaf Hering <olh@suse.de> from novell bug #105878 */
+UNUSUAL_DEV( 0x0424, 0x0fdc, 0x0210, 0x0210,
+ "SMSC",
+ "FDC GOLD-2.30",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_SINGLE_LUN ),
+
#ifdef CONFIG_USB_STORAGE_DPCM
UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100,
"Microtech",
@@ -103,6 +120,24 @@ UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100,
US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ),
#endif
+/*
+ * Pete Zaitcev <zaitcev@yahoo.com>, from Patrick C. F. Ernzer, bz#162559.
+ * The key does not actually break, but it returns zero sense which
+ * makes our SCSI stack to print confusing messages.
+ */
+UNUSUAL_DEV( 0x0457, 0x0150, 0x0100, 0x0100,
+ "USBest Technology", /* sold by Transcend */
+ "USB Mass Storage Device",
+ US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),
+
+/* Patch submitted by Daniel Drake <dsd@gentoo.org>
+ * Device reports nonsense bInterfaceProtocol 6 when connected over USB2 */
+UNUSUAL_DEV( 0x0451, 0x5416, 0x0100, 0x0100,
+ "Neuros Audio",
+ "USB 2.0 HD 2.5",
+ US_SC_DEVICE, US_PR_BULK, NULL,
+ US_FL_NEED_OVERRIDE ),
+
/* Patch submitted by Philipp Friedrich <philipp@void.at> */
UNUSUAL_DEV( 0x0482, 0x0100, 0x0100, 0x0100,
"Kyocera",
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index cb4c770baf3..f9a9bfa1aef 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -392,11 +392,16 @@ SkipForAbort:
/* If an abort request was received we need to signal that
* the abort has finished. The proper test for this is
* the TIMED_OUT flag, not srb->result == DID_ABORT, because
- * a timeout/abort request might be received after all the
- * USB processing was complete. */
- if (test_bit(US_FLIDX_TIMED_OUT, &us->flags))
+ * the timeout might have occurred after the command had
+ * already completed with a different result code. */
+ if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {
complete(&(us->notify));
+ /* Allow USB transfers to resume */
+ clear_bit(US_FLIDX_ABORTING, &us->flags);
+ clear_bit(US_FLIDX_TIMED_OUT, &us->flags);
+ }
+
/* finished working on this command */
us->srb = NULL;
scsi_unlock(host);