summaryrefslogtreecommitdiffstats
path: root/drivers/usb/storage/uas.c
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2011-12-19 17:06:08 +0100
committerSebastian Andrzej Siewior <bigeasy@linutronix.de>2011-12-22 10:14:49 +0100
commitdae51546b6564b06cbae4191d4f2dee7136be3c1 (patch)
tree6d5654cb4c00546245bdb8621a7a0d647ab9bb36 /drivers/usb/storage/uas.c
parent96c1eb9873caffc507a1951c36b43fdcf3ddeff3 (diff)
usb/uas: use unique tags for all LUNs
I observed that on a device with multiple LUNs UAS was re-using the same tag number for requests which were issued at the same time to both LUNs. This patch uses scsi_init_shared_tag_map() to use unique tags for all LUNs. With this patch I haven't seen the same tag number during the init sequence anymore. Tag 1 is used for devices which do not adverise command queueing. This patch initilizes the queue before adding the scsi host like the other two user in tree. Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Diffstat (limited to 'drivers/usb/storage/uas.c')
-rw-r--r--drivers/usb/storage/uas.c38
1 files changed, 25 insertions, 13 deletions
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 9dd4aaee85c..6974f4bed2f 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -684,6 +684,17 @@ static void uas_configure_endpoints(struct uas_dev_info *devinfo)
}
}
+static void uas_free_streams(struct uas_dev_info *devinfo)
+{
+ struct usb_device *udev = devinfo->udev;
+ struct usb_host_endpoint *eps[3];
+
+ eps[0] = usb_pipe_endpoint(udev, devinfo->status_pipe);
+ eps[1] = usb_pipe_endpoint(udev, devinfo->data_in_pipe);
+ eps[2] = usb_pipe_endpoint(udev, devinfo->data_out_pipe);
+ usb_free_streams(devinfo->intf, eps, 3, GFP_KERNEL);
+}
+
/*
* XXX: What I'd like to do here is register a SCSI host for each USB host in
* the system. Follow usb-storage's design of registering a SCSI host for
@@ -713,18 +724,26 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id)
shost->max_id = 1;
shost->sg_tablesize = udev->bus->sg_tablesize;
- result = scsi_add_host(shost, &intf->dev);
- if (result)
- goto free;
- shost->hostdata[0] = (unsigned long)devinfo;
-
devinfo->intf = intf;
devinfo->udev = udev;
uas_configure_endpoints(devinfo);
+ result = scsi_init_shared_tag_map(shost, devinfo->qdepth - 1);
+ if (result)
+ goto free;
+
+ result = scsi_add_host(shost, &intf->dev);
+ if (result)
+ goto deconfig_eps;
+
+ shost->hostdata[0] = (unsigned long)devinfo;
+
scsi_scan_host(shost);
usb_set_intfdata(intf, shost);
return result;
+
+deconfig_eps:
+ uas_free_streams(devinfo);
free:
kfree(devinfo);
if (shost)
@@ -746,18 +765,11 @@ static int uas_post_reset(struct usb_interface *intf)
static void uas_disconnect(struct usb_interface *intf)
{
- struct usb_device *udev = interface_to_usbdev(intf);
- struct usb_host_endpoint *eps[3];
struct Scsi_Host *shost = usb_get_intfdata(intf);
struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
scsi_remove_host(shost);
-
- eps[0] = usb_pipe_endpoint(udev, devinfo->status_pipe);
- eps[1] = usb_pipe_endpoint(udev, devinfo->data_in_pipe);
- eps[2] = usb_pipe_endpoint(udev, devinfo->data_out_pipe);
- usb_free_streams(intf, eps, 3, GFP_KERNEL);
-
+ uas_free_streams(devinfo);
kfree(devinfo);
}