[PATCH 02/14] uas: reserve a tag for management

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux