UAS uses a shared tag space. We reserve tag #1 for management. That leaves us with an offset of 2. Signed-off-by: Oliver Neukum <oneukum@xxxxxxxx> --- drivers/usb/storage/uas.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 13e6313..a8052ec 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -32,6 +32,12 @@ #define MAX_CMNDS 256 +/* + * 1 is due to the different base + * and 1 is reserved for the tmf + */ +#define TAG_OFFSET (1 + 1) + struct uas_dev_info { struct usb_interface *intf; struct usb_device *udev; @@ -97,7 +103,7 @@ static void uas_do_work(struct work_struct *work) if (devinfo->resetting) goto out; - for (i = 0; i < devinfo->qdepth; i++) { + for (i = 0; i < devinfo->qdepth - 1; i++) { if (!devinfo->cmnd[i]) continue; @@ -229,7 +235,7 @@ static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller) DATA_OUT_URB_INFLIGHT | COMMAND_ABORTED)) return -EBUSY; - devinfo->cmnd[cmdinfo->uas_tag - 1] = NULL; + devinfo->cmnd[cmdinfo->uas_tag - TAG_OFFSET] = NULL; uas_free_unsubmitted_urbs(cmnd); cmnd->scsi_done(cmnd); return 0; @@ -296,10 +302,10 @@ static void uas_stat_cmplt(struct urb *urb) goto out; } - idx = be16_to_cpup(&iu->tag) - 1; + idx = be16_to_cpup(&iu->tag) - TAG_OFFSET; if (idx >= MAX_CMNDS || !devinfo->cmnd[idx]) { dev_err(&urb->dev->dev, - "stat urb: no pending cmd for uas-tag %d\n", idx + 1); + "stat urb: no pending cmd for uas-tag %d\n", idx + TAG_OFFSET); goto out; } @@ -653,7 +659,7 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd, if (!devinfo->cmnd[idx]) break; } - if (idx == devinfo->qdepth) { + if (idx >= devinfo->qdepth - 1) { spin_unlock_irqrestore(&devinfo->lock, flags); return SCSI_MLQUEUE_DEVICE_BUSY; } @@ -661,7 +667,11 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd, cmnd->scsi_done = done; memset(cmdinfo, 0, sizeof(*cmdinfo)); - cmdinfo->uas_tag = idx + 1; /* uas-tag == usb-stream-id, so 1 based */ + cmdinfo->uas_tag = idx + TAG_OFFSET; + /* + * uas-tag == usb-stream-id, so 1 based + * and 1 reserved for management + */ cmdinfo->state = SUBMIT_STATUS_URB | ALLOC_CMD_URB | SUBMIT_CMD_URB; switch (cmnd->sc_data_direction) { @@ -717,7 +727,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[cmdinfo->uas_tag - 1] = NULL; + devinfo->cmnd[cmdinfo->uas_tag - TAG_OFFSET] = 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) @@ -826,7 +836,13 @@ static int uas_slave_configure(struct scsi_device *sdev) if (devinfo->flags & US_FL_BROKEN_FUA) sdev->broken_fua = 1; - scsi_change_queue_depth(sdev, devinfo->qdepth - 2); + /* + * We take three slots, one each for + * - untagged commands + * - guarding against firmware bugs about the indexing + * - the TMF tag + */ + scsi_change_queue_depth(sdev, devinfo->qdepth - 3); return 0; } -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html