aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/storage
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-12-14 14:57:16 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-14 14:57:16 -0800
commite7cf773d431a63a2417902696fcc9e0ebdc83bbe (patch)
tree86dbdceb7d91226507a3af0d57e03b0ca664b22e /drivers/usb/storage
parent7a02d089695a1217992434f03a78aa32bad85b5c (diff)
parent81e1dadfb5b2d47aa513ad60b1c9cf0ea17b6514 (diff)
Merge tag 'usb-3.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB updates from Greg KH: "Here's the big set of USB and PHY patches for 3.19-rc1. The normal churn in the USB gadget area is in here, as well as xhci and other individual USB driver updates. The PHY tree is also in here, as there were dependancies on the USB tree. All of these have been in linux-next" * tag 'usb-3.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (351 commits) arm: omap3: twl: remove usb phy init data usbip: fix error handling in stub_probe() usb: gadget: udc: missing curly braces USB: mos7720: delete some unneeded code wusb: replace memset by memzero_explicit usbip: remove unneeded structure usb: xhci: fix comment for PORT_DEV_REMOVE xhci: don't use the same variable for stopped and halted rings current TD xhci: clear extra bits from slot context when setting max exit latency xhci: cleanup finish_td function USB: adutux: NULL dereferences on disconnect usb: chipidea: fix platform_no_drv_owner.cocci warnings usb: chipidea: Fixed a few typos in comments Documentation: bindings: add doc for the USB2 ChipIdea USB driver usb: chipidea: add a usb2 driver for ci13xxx usb: chipidea: fix phy handling usb: chipidea: remove duplicate dev_set_drvdata for host_start usb: chipidea: parameter 'mode' isn't needed for hw_device_reset usb: chipidea: add controller reset API usb: chipidea: remove flag CI_HDRC_REQUIRE_TRANSCEIVER ...
Diffstat (limited to 'drivers/usb/storage')
-rw-r--r--drivers/usb/storage/debug.c7
-rw-r--r--drivers/usb/storage/debug.h10
-rw-r--r--drivers/usb/storage/initializers.c3
-rw-r--r--drivers/usb/storage/transport.c17
-rw-r--r--drivers/usb/storage/uas.c64
-rw-r--r--drivers/usb/storage/usb.c36
6 files changed, 70 insertions, 67 deletions
diff --git a/drivers/usb/storage/debug.c b/drivers/usb/storage/debug.c
index 2d81e1d8ee30..57bf3ad41fb6 100644
--- a/drivers/usb/storage/debug.c
+++ b/drivers/usb/storage/debug.c
@@ -181,17 +181,14 @@ void usb_stor_show_sense(const struct us_data *us,
US_DEBUGPX("%s\n", what);
}
-int usb_stor_dbg(const struct us_data *us, const char *fmt, ...)
+void usb_stor_dbg(const struct us_data *us, const char *fmt, ...)
{
va_list args;
- int r;
va_start(args, fmt);
- r = dev_vprintk_emit(LOGLEVEL_DEBUG, &us->pusb_dev->dev, fmt, args);
+ dev_vprintk_emit(LOGLEVEL_DEBUG, &us->pusb_dev->dev, fmt, args);
va_end(args);
-
- return r;
}
EXPORT_SYMBOL_GPL(usb_stor_dbg);
diff --git a/drivers/usb/storage/debug.h b/drivers/usb/storage/debug.h
index b1273f03e223..f52520306e1a 100644
--- a/drivers/usb/storage/debug.h
+++ b/drivers/usb/storage/debug.h
@@ -50,15 +50,17 @@
void usb_stor_show_command(const struct us_data *us, struct scsi_cmnd *srb);
void usb_stor_show_sense(const struct us_data *us, unsigned char key,
unsigned char asc, unsigned char ascq);
-__printf(2, 3) int usb_stor_dbg(const struct us_data *us,
- const char *fmt, ...);
+__printf(2, 3) void usb_stor_dbg(const struct us_data *us,
+ const char *fmt, ...);
#define US_DEBUGPX(fmt, ...) printk(fmt, ##__VA_ARGS__)
#define US_DEBUG(x) x
#else
__printf(2, 3)
-static inline int _usb_stor_dbg(const struct us_data *us,
- const char *fmt, ...) {return 1;}
+static inline void _usb_stor_dbg(const struct us_data *us,
+ const char *fmt, ...)
+{
+}
#define usb_stor_dbg(us, fmt, ...) \
do { if (0) _usb_stor_dbg(us, fmt, ##__VA_ARGS__); } while (0)
#define US_DEBUGPX(fmt, ...) \
diff --git a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c
index 73f125e0cb58..31fa2e92065b 100644
--- a/drivers/usb/storage/initializers.c
+++ b/drivers/usb/storage/initializers.c
@@ -49,10 +49,9 @@ int usb_stor_euscsi_init(struct us_data *us)
int result;
usb_stor_dbg(us, "Attempting to init eUSCSI bridge...\n");
- us->iobuf[0] = 0x1;
result = usb_stor_control_msg(us, us->send_ctrl_pipe,
0x0C, USB_RECIP_INTERFACE | USB_TYPE_VENDOR,
- 0x01, 0x0, us->iobuf, 0x1, 5 * HZ);
+ 0x01, 0x0, NULL, 0x0, 5 * HZ);
usb_stor_dbg(us, "-- result is %d\n", result);
return 0;
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index b1d815eb6d0b..540add24a12f 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -1035,9 +1035,20 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
usb_stor_dbg(us, "GetMaxLUN command result is %d, data is %d\n",
result, us->iobuf[0]);
- /* if we have a successful request, return the result */
- if (result > 0)
- return us->iobuf[0];
+ /*
+ * If we have a successful request, return the result if valid. The
+ * CBW LUN field is 4 bits wide, so the value reported by the device
+ * should fit into that.
+ */
+ if (result > 0) {
+ if (us->iobuf[0] < 16) {
+ return us->iobuf[0];
+ } else {
+ dev_info(&us->pusb_intf->dev,
+ "Max LUN %d is not valid, using 0 instead",
+ us->iobuf[0]);
+ }
+ }
/*
* Some devices don't like GetMaxLUN. They may STALL the control
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 4047edfb64e1..6cdabdc119a7 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -66,7 +66,7 @@ enum {
/* Overrides scsi_pointer */
struct uas_cmd_info {
unsigned int state;
- unsigned int stream;
+ unsigned int uas_tag;
struct urb *cmd_urb;
struct urb *data_in_urb;
struct urb *data_out_urb;
@@ -173,30 +173,15 @@ static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd)
cmnd->result = sense_iu->status;
}
-/*
- * scsi-tags go from 0 - (nr_tags - 1), uas tags need to match stream-ids,
- * which go from 1 - nr_streams. And we use 1 for untagged commands.
- */
-static int uas_get_tag(struct scsi_cmnd *cmnd)
-{
- int tag;
-
- if (cmnd->flags & SCMD_TAGGED)
- tag = cmnd->request->tag + 2;
- else
- tag = 1;
-
- return tag;
-}
-
static void uas_log_cmd_state(struct scsi_cmnd *cmnd, const char *prefix,
int status)
{
struct uas_cmd_info *ci = (void *)&cmnd->SCp;
+ struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
scmd_printk(KERN_INFO, cmnd,
- "%s %d tag %d inflight:%s%s%s%s%s%s%s%s%s%s%s%s ",
- prefix, status, uas_get_tag(cmnd),
+ "%s %d uas-tag %d inflight:%s%s%s%s%s%s%s%s%s%s%s%s ",
+ prefix, status, cmdinfo->uas_tag,
(ci->state & SUBMIT_STATUS_URB) ? " s-st" : "",
(ci->state & ALLOC_DATA_IN_URB) ? " a-in" : "",
(ci->state & SUBMIT_DATA_IN_URB) ? " s-in" : "",
@@ -242,7 +227,7 @@ static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller)
DATA_OUT_URB_INFLIGHT |
COMMAND_ABORTED))
return -EBUSY;
- devinfo->cmnd[uas_get_tag(cmnd) - 1] = NULL;
+ devinfo->cmnd[cmdinfo->uas_tag - 1] = NULL;
uas_free_unsubmitted_urbs(cmnd);
cmnd->scsi_done(cmnd);
return 0;
@@ -289,7 +274,7 @@ static void uas_stat_cmplt(struct urb *urb)
idx = be16_to_cpup(&iu->tag) - 1;
if (idx >= MAX_CMNDS || !devinfo->cmnd[idx]) {
dev_err(&urb->dev->dev,
- "stat urb: no pending cmd for tag %d\n", idx + 1);
+ "stat urb: no pending cmd for uas-tag %d\n", idx + 1);
goto out;
}
@@ -427,7 +412,8 @@ static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp,
goto out;
usb_fill_bulk_urb(urb, udev, pipe, NULL, sdb->length,
uas_data_cmplt, cmnd);
- urb->stream_id = cmdinfo->stream;
+ if (devinfo->use_streams)
+ urb->stream_id = cmdinfo->uas_tag;
urb->num_sgs = udev->bus->sg_tablesize ? sdb->table.nents : 0;
urb->sg = sdb->table.sgl;
out:
@@ -451,7 +437,8 @@ static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp,
usb_fill_bulk_urb(urb, udev, devinfo->status_pipe, iu, sizeof(*iu),
uas_stat_cmplt, cmnd->device->host);
- urb->stream_id = cmdinfo->stream;
+ if (devinfo->use_streams)
+ urb->stream_id = cmdinfo->uas_tag;
urb->transfer_flags |= URB_FREE_BUFFER;
out:
return urb;
@@ -465,6 +452,7 @@ static struct urb *uas_alloc_cmd_urb(struct uas_dev_info *devinfo, gfp_t gfp,
{
struct usb_device *udev = devinfo->udev;
struct scsi_device *sdev = cmnd->device;
+ struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
struct urb *urb = usb_alloc_urb(0, gfp);
struct command_iu *iu;
int len;
@@ -481,7 +469,7 @@ static struct urb *uas_alloc_cmd_urb(struct uas_dev_info *devinfo, gfp_t gfp,
goto free;
iu->iu_id = IU_ID_COMMAND;
- iu->tag = cpu_to_be16(uas_get_tag(cmnd));
+ iu->tag = cpu_to_be16(cmdinfo->uas_tag);
iu->prio_attr = UAS_SIMPLE_TAG;
iu->len = len;
int_to_scsilun(sdev->lun, &iu->lun);
@@ -608,8 +596,7 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
struct uas_dev_info *devinfo = sdev->hostdata;
struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
unsigned long flags;
- unsigned int stream;
- int err;
+ int idx, err;
BUILD_BUG_ON(sizeof(struct uas_cmd_info) > sizeof(struct scsi_pointer));
@@ -635,8 +622,12 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
return 0;
}
- stream = uas_get_tag(cmnd);
- if (devinfo->cmnd[stream - 1]) {
+ /* Find a free uas-tag */
+ for (idx = 0; idx < devinfo->qdepth; idx++) {
+ if (!devinfo->cmnd[idx])
+ break;
+ }
+ if (idx == devinfo->qdepth) {
spin_unlock_irqrestore(&devinfo->lock, flags);
return SCSI_MLQUEUE_DEVICE_BUSY;
}
@@ -644,7 +635,7 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
cmnd->scsi_done = done;
memset(cmdinfo, 0, sizeof(*cmdinfo));
- cmdinfo->stream = stream;
+ cmdinfo->uas_tag = idx + 1; /* uas-tag == usb-stream-id, so 1 based */
cmdinfo->state = SUBMIT_STATUS_URB | ALLOC_CMD_URB | SUBMIT_CMD_URB;
switch (cmnd->sc_data_direction) {
@@ -659,10 +650,8 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
break;
}
- if (!devinfo->use_streams) {
+ if (!devinfo->use_streams)
cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB);
- cmdinfo->stream = 0;
- }
err = uas_submit_urbs(cmnd, devinfo, GFP_ATOMIC);
if (err) {
@@ -674,7 +663,7 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
uas_add_work(cmdinfo);
}
- devinfo->cmnd[stream - 1] = cmnd;
+ devinfo->cmnd[idx] = cmnd;
spin_unlock_irqrestore(&devinfo->lock, flags);
return 0;
}
@@ -702,7 +691,7 @@ static int uas_eh_abort_handler(struct scsi_cmnd *cmnd)
cmdinfo->state |= COMMAND_ABORTED;
/* Drop all refs to this cmnd, kill data urbs to break their ref */
- devinfo->cmnd[uas_get_tag(cmnd) - 1] = NULL;
+ devinfo->cmnd[cmdinfo->uas_tag - 1] = NULL;
if (cmdinfo->state & DATA_IN_URB_INFLIGHT)
data_in_urb = usb_get_urb(cmdinfo->data_in_urb);
if (cmdinfo->state & DATA_OUT_URB_INFLIGHT)
@@ -816,13 +805,6 @@ static struct scsi_host_template uas_host_template = {
.sg_tablesize = SG_NONE,
.cmd_per_lun = 1, /* until we override it */
.skip_settle_delay = 1,
-
- /*
- * The uas drivers expects tags not to be bigger than the maximum
- * per-device queue depth, which is not true with the blk-mq tag
- * allocator.
- */
- .disable_blk_mq = true,
.use_blk_tags = 1,
};
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 9d66ce62542e..d468d02179f4 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -884,7 +884,9 @@ static void usb_stor_scan_dwork(struct work_struct *work)
dev_dbg(dev, "starting scan\n");
/* For bulk-only devices, determine the max LUN value */
- if (us->protocol == USB_PR_BULK && !(us->fflags & US_FL_SINGLE_LUN)) {
+ if (us->protocol == USB_PR_BULK &&
+ !(us->fflags & US_FL_SINGLE_LUN) &&
+ !(us->fflags & US_FL_SCM_MULT_TARG)) {
mutex_lock(&us->dev_mutex);
us->max_lun = usb_stor_Bulk_max_lun(us);
mutex_unlock(&us->dev_mutex);
@@ -983,21 +985,31 @@ int usb_stor_probe2(struct us_data *us)
usb_stor_dbg(us, "Transport: %s\n", us->transport_name);
usb_stor_dbg(us, "Protocol: %s\n", us->protocol_name);
+ if (us->fflags & US_FL_SCM_MULT_TARG) {
+ /*
+ * SCM eUSCSI bridge devices can have different numbers
+ * of LUNs on different targets; allow all to be probed.
+ */
+ us->max_lun = 7;
+ /* The eUSCSI itself has ID 7, so avoid scanning that */
+ us_to_host(us)->this_id = 7;
+ /* max_id is 8 initially, so no need to set it here */
+ } else {
+ /* In the normal case there is only a single target */
+ us_to_host(us)->max_id = 1;
+ /*
+ * Like Windows, we won't store the LUN bits in CDB[1] for
+ * SCSI-2 devices using the Bulk-Only transport (even though
+ * this violates the SCSI spec).
+ */
+ if (us->transport == usb_stor_Bulk_transport)
+ us_to_host(us)->no_scsi2_lun_in_cdb = 1;
+ }
+
/* fix for single-lun devices */
if (us->fflags & US_FL_SINGLE_LUN)
us->max_lun = 0;
- if (!(us->fflags & US_FL_SCM_MULT_TARG))
- us_to_host(us)->max_id = 1;
-
- /*
- * Like Windows, we won't store the LUN bits in CDB[1] for SCSI-2
- * devices using the Bulk-Only transport (even though this violates
- * the SCSI spec).
- */
- if (us->transport == usb_stor_Bulk_transport)
- us_to_host(us)->no_scsi2_lun_in_cdb = 1;
-
/* Find the endpoints and calculate pipe values */
result = get_pipes(us);
if (result)