aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/storage
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2014-10-12 06:19:40 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-11-03 18:34:00 -0500
commite28e2f2f7c42e5b9dd4c965a0245267e44a8a7ae (patch)
treed03d3f98fe2a92f51a5a9a55606a84306251b6e9 /drivers/usb/storage
parent1cc373c654acde47d78da9cccb5732dab2cc584f (diff)
uas: Make uas work with blk-mq
With uas over usb-3 the tags inside the uas iu-s must match the usb-3 stream ids, and those go from 1 - qdepth. Before blk-mq calling scsi_activate_tcq(sdev, qdepth) guaranteed that we would only get cmnd->request->tag from 0 - (qdepth - 1), and we used those as uas-tags / stream-ids. With blk-mq however we are guaranteed to never get more then qdepth commands queued at the same time, but the cmnd->request->tag values may be much larger, which breaks uas. This commit fixes this by generating uas tags in the 1 - qdepth range ourselves instead of using cmnd->request->tag. While touching all involved code anyways also rename the uas_cmd_info stream field to uas_tag, because when using uas over usb-2 streams are not used. Cc: Christoph Hellwig <hch@infradead.org> Reported-by: Douglas Gilbert <dgilbert@interlog.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> -- Changes in v2: -Remove ".disable_blk_mq = true" from uas_host_template Changes in v3: -Rebased on top of Linus' current master branch Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/storage')
-rw-r--r--drivers/usb/storage/uas.c64
1 files changed, 23 insertions, 41 deletions
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 89b24349269e..004ebc12bc21 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -66,7 +66,7 @@ enum {
66/* Overrides scsi_pointer */ 66/* Overrides scsi_pointer */
67struct uas_cmd_info { 67struct uas_cmd_info {
68 unsigned int state; 68 unsigned int state;
69 unsigned int stream; 69 unsigned int uas_tag;
70 struct urb *cmd_urb; 70 struct urb *cmd_urb;
71 struct urb *data_in_urb; 71 struct urb *data_in_urb;
72 struct urb *data_out_urb; 72 struct urb *data_out_urb;
@@ -173,30 +173,15 @@ static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd)
173 cmnd->result = sense_iu->status; 173 cmnd->result = sense_iu->status;
174} 174}
175 175
176/*
177 * scsi-tags go from 0 - (nr_tags - 1), uas tags need to match stream-ids,
178 * which go from 1 - nr_streams. And we use 1 for untagged commands.
179 */
180static int uas_get_tag(struct scsi_cmnd *cmnd)
181{
182 int tag;
183
184 if (blk_rq_tagged(cmnd->request))
185 tag = cmnd->request->tag + 2;
186 else
187 tag = 1;
188
189 return tag;
190}
191
192static void uas_log_cmd_state(struct scsi_cmnd *cmnd, const char *prefix, 176static void uas_log_cmd_state(struct scsi_cmnd *cmnd, const char *prefix,
193 int status) 177 int status)
194{ 178{
195 struct uas_cmd_info *ci = (void *)&cmnd->SCp; 179 struct uas_cmd_info *ci = (void *)&cmnd->SCp;
180 struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
196 181
197 scmd_printk(KERN_INFO, cmnd, 182 scmd_printk(KERN_INFO, cmnd,
198 "%s %d tag %d inflight:%s%s%s%s%s%s%s%s%s%s%s%s ", 183 "%s %d uas-tag %d inflight:%s%s%s%s%s%s%s%s%s%s%s%s ",
199 prefix, status, uas_get_tag(cmnd), 184 prefix, status, cmdinfo->uas_tag,
200 (ci->state & SUBMIT_STATUS_URB) ? " s-st" : "", 185 (ci->state & SUBMIT_STATUS_URB) ? " s-st" : "",
201 (ci->state & ALLOC_DATA_IN_URB) ? " a-in" : "", 186 (ci->state & ALLOC_DATA_IN_URB) ? " a-in" : "",
202 (ci->state & SUBMIT_DATA_IN_URB) ? " s-in" : "", 187 (ci->state & SUBMIT_DATA_IN_URB) ? " s-in" : "",
@@ -242,7 +227,7 @@ static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller)
242 DATA_OUT_URB_INFLIGHT | 227 DATA_OUT_URB_INFLIGHT |
243 COMMAND_ABORTED)) 228 COMMAND_ABORTED))
244 return -EBUSY; 229 return -EBUSY;
245 devinfo->cmnd[uas_get_tag(cmnd) - 1] = NULL; 230 devinfo->cmnd[cmdinfo->uas_tag - 1] = NULL;
246 uas_free_unsubmitted_urbs(cmnd); 231 uas_free_unsubmitted_urbs(cmnd);
247 cmnd->scsi_done(cmnd); 232 cmnd->scsi_done(cmnd);
248 return 0; 233 return 0;
@@ -289,7 +274,7 @@ static void uas_stat_cmplt(struct urb *urb)
289 idx = be16_to_cpup(&iu->tag) - 1; 274 idx = be16_to_cpup(&iu->tag) - 1;
290 if (idx >= MAX_CMNDS || !devinfo->cmnd[idx]) { 275 if (idx >= MAX_CMNDS || !devinfo->cmnd[idx]) {
291 dev_err(&urb->dev->dev, 276 dev_err(&urb->dev->dev,
292 "stat urb: no pending cmd for tag %d\n", idx + 1); 277 "stat urb: no pending cmd for uas-tag %d\n", idx + 1);
293 goto out; 278 goto out;
294 } 279 }
295 280
@@ -427,7 +412,8 @@ static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp,
427 goto out; 412 goto out;
428 usb_fill_bulk_urb(urb, udev, pipe, NULL, sdb->length, 413 usb_fill_bulk_urb(urb, udev, pipe, NULL, sdb->length,
429 uas_data_cmplt, cmnd); 414 uas_data_cmplt, cmnd);
430 urb->stream_id = cmdinfo->stream; 415 if (devinfo->use_streams)
416 urb->stream_id = cmdinfo->uas_tag;
431 urb->num_sgs = udev->bus->sg_tablesize ? sdb->table.nents : 0; 417 urb->num_sgs = udev->bus->sg_tablesize ? sdb->table.nents : 0;
432 urb->sg = sdb->table.sgl; 418 urb->sg = sdb->table.sgl;
433 out: 419 out:
@@ -451,7 +437,8 @@ static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp,
451 437
452 usb_fill_bulk_urb(urb, udev, devinfo->status_pipe, iu, sizeof(*iu), 438 usb_fill_bulk_urb(urb, udev, devinfo->status_pipe, iu, sizeof(*iu),
453 uas_stat_cmplt, cmnd->device->host); 439 uas_stat_cmplt, cmnd->device->host);
454 urb->stream_id = cmdinfo->stream; 440 if (devinfo->use_streams)
441 urb->stream_id = cmdinfo->uas_tag;
455 urb->transfer_flags |= URB_FREE_BUFFER; 442 urb->transfer_flags |= URB_FREE_BUFFER;
456 out: 443 out:
457 return urb; 444 return urb;
@@ -465,6 +452,7 @@ static struct urb *uas_alloc_cmd_urb(struct uas_dev_info *devinfo, gfp_t gfp,
465{ 452{
466 struct usb_device *udev = devinfo->udev; 453 struct usb_device *udev = devinfo->udev;
467 struct scsi_device *sdev = cmnd->device; 454 struct scsi_device *sdev = cmnd->device;
455 struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
468 struct urb *urb = usb_alloc_urb(0, gfp); 456 struct urb *urb = usb_alloc_urb(0, gfp);
469 struct command_iu *iu; 457 struct command_iu *iu;
470 int len; 458 int len;
@@ -481,7 +469,7 @@ static struct urb *uas_alloc_cmd_urb(struct uas_dev_info *devinfo, gfp_t gfp,
481 goto free; 469 goto free;
482 470
483 iu->iu_id = IU_ID_COMMAND; 471 iu->iu_id = IU_ID_COMMAND;
484 iu->tag = cpu_to_be16(uas_get_tag(cmnd)); 472 iu->tag = cpu_to_be16(cmdinfo->uas_tag);
485 iu->prio_attr = UAS_SIMPLE_TAG; 473 iu->prio_attr = UAS_SIMPLE_TAG;
486 iu->len = len; 474 iu->len = len;
487 int_to_scsilun(sdev->lun, &iu->lun); 475 int_to_scsilun(sdev->lun, &iu->lun);
@@ -608,8 +596,7 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
608 struct uas_dev_info *devinfo = sdev->hostdata; 596 struct uas_dev_info *devinfo = sdev->hostdata;
609 struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; 597 struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
610 unsigned long flags; 598 unsigned long flags;
611 unsigned int stream; 599 int idx, err;
612 int err;
613 600
614 BUILD_BUG_ON(sizeof(struct uas_cmd_info) > sizeof(struct scsi_pointer)); 601 BUILD_BUG_ON(sizeof(struct uas_cmd_info) > sizeof(struct scsi_pointer));
615 602
@@ -635,8 +622,12 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
635 return 0; 622 return 0;
636 } 623 }
637 624
638 stream = uas_get_tag(cmnd); 625 /* Find a free uas-tag */
639 if (devinfo->cmnd[stream - 1]) { 626 for (idx = 0; idx < devinfo->qdepth; idx++) {
627 if (!devinfo->cmnd[idx])
628 break;
629 }
630 if (idx == devinfo->qdepth) {
640 spin_unlock_irqrestore(&devinfo->lock, flags); 631 spin_unlock_irqrestore(&devinfo->lock, flags);
641 return SCSI_MLQUEUE_DEVICE_BUSY; 632 return SCSI_MLQUEUE_DEVICE_BUSY;
642 } 633 }
@@ -644,7 +635,7 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
644 cmnd->scsi_done = done; 635 cmnd->scsi_done = done;
645 636
646 memset(cmdinfo, 0, sizeof(*cmdinfo)); 637 memset(cmdinfo, 0, sizeof(*cmdinfo));
647 cmdinfo->stream = stream; 638 cmdinfo->uas_tag = idx + 1; /* uas-tag == usb-stream-id, so 1 based */
648 cmdinfo->state = SUBMIT_STATUS_URB | ALLOC_CMD_URB | SUBMIT_CMD_URB; 639 cmdinfo->state = SUBMIT_STATUS_URB | ALLOC_CMD_URB | SUBMIT_CMD_URB;
649 640
650 switch (cmnd->sc_data_direction) { 641 switch (cmnd->sc_data_direction) {
@@ -659,10 +650,8 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
659 break; 650 break;
660 } 651 }
661 652
662 if (!devinfo->use_streams) { 653 if (!devinfo->use_streams)
663 cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB); 654 cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB);
664 cmdinfo->stream = 0;
665 }
666 655
667 err = uas_submit_urbs(cmnd, devinfo, GFP_ATOMIC); 656 err = uas_submit_urbs(cmnd, devinfo, GFP_ATOMIC);
668 if (err) { 657 if (err) {
@@ -674,7 +663,7 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
674 uas_add_work(cmdinfo); 663 uas_add_work(cmdinfo);
675 } 664 }
676 665
677 devinfo->cmnd[stream - 1] = cmnd; 666 devinfo->cmnd[idx] = cmnd;
678 spin_unlock_irqrestore(&devinfo->lock, flags); 667 spin_unlock_irqrestore(&devinfo->lock, flags);
679 return 0; 668 return 0;
680} 669}
@@ -702,7 +691,7 @@ static int uas_eh_abort_handler(struct scsi_cmnd *cmnd)
702 cmdinfo->state |= COMMAND_ABORTED; 691 cmdinfo->state |= COMMAND_ABORTED;
703 692
704 /* Drop all refs to this cmnd, kill data urbs to break their ref */ 693 /* Drop all refs to this cmnd, kill data urbs to break their ref */
705 devinfo->cmnd[uas_get_tag(cmnd) - 1] = NULL; 694 devinfo->cmnd[cmdinfo->uas_tag - 1] = NULL;
706 if (cmdinfo->state & DATA_IN_URB_INFLIGHT) 695 if (cmdinfo->state & DATA_IN_URB_INFLIGHT)
707 data_in_urb = usb_get_urb(cmdinfo->data_in_urb); 696 data_in_urb = usb_get_urb(cmdinfo->data_in_urb);
708 if (cmdinfo->state & DATA_OUT_URB_INFLIGHT) 697 if (cmdinfo->state & DATA_OUT_URB_INFLIGHT)
@@ -818,13 +807,6 @@ static struct scsi_host_template uas_host_template = {
818 .cmd_per_lun = 1, /* until we override it */ 807 .cmd_per_lun = 1, /* until we override it */
819 .skip_settle_delay = 1, 808 .skip_settle_delay = 1,
820 .ordered_tag = 1, 809 .ordered_tag = 1,
821
822 /*
823 * The uas drivers expects tags not to be bigger than the maximum
824 * per-device queue depth, which is not true with the blk-mq tag
825 * allocator.
826 */
827 .disable_blk_mq = true,
828}; 810};
829 811
830#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ 812#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \