diff options
| author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2011-12-19 17:06:08 +0100 | 
|---|---|---|
| committer | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2011-12-22 10:14:49 +0100 | 
| commit | dae51546b6564b06cbae4191d4f2dee7136be3c1 (patch) | |
| tree | 6d5654cb4c00546245bdb8621a7a0d647ab9bb36 | |
| parent | 96c1eb9873caffc507a1951c36b43fdcf3ddeff3 (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>
| -rw-r--r-- | drivers/usb/storage/uas.c | 38 | 
1 files changed, 25 insertions, 13 deletions
| diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 9dd4aaee85cc..6974f4bed2fd 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);  } | 
