diff options
author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2011-12-19 11:06:08 -0500 |
---|---|---|
committer | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2011-12-22 04:14:49 -0500 |
commit | dae51546b6564b06cbae4191d4f2dee7136be3c1 (patch) | |
tree | 6d5654cb4c00546245bdb8621a7a0d647ab9bb36 /drivers/usb/storage | |
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>
Diffstat (limited to 'drivers/usb/storage')
-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) | |||
684 | } | 684 | } |
685 | } | 685 | } |
686 | 686 | ||
687 | static void uas_free_streams(struct uas_dev_info *devinfo) | ||
688 | { | ||
689 | struct usb_device *udev = devinfo->udev; | ||
690 | struct usb_host_endpoint *eps[3]; | ||
691 | |||
692 | eps[0] = usb_pipe_endpoint(udev, devinfo->status_pipe); | ||
693 | eps[1] = usb_pipe_endpoint(udev, devinfo->data_in_pipe); | ||
694 | eps[2] = usb_pipe_endpoint(udev, devinfo->data_out_pipe); | ||
695 | usb_free_streams(devinfo->intf, eps, 3, GFP_KERNEL); | ||
696 | } | ||
697 | |||
687 | /* | 698 | /* |
688 | * XXX: What I'd like to do here is register a SCSI host for each USB host in | 699 | * XXX: What I'd like to do here is register a SCSI host for each USB host in |
689 | * the system. Follow usb-storage's design of registering a SCSI host for | 700 | * 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) | |||
713 | shost->max_id = 1; | 724 | shost->max_id = 1; |
714 | shost->sg_tablesize = udev->bus->sg_tablesize; | 725 | shost->sg_tablesize = udev->bus->sg_tablesize; |
715 | 726 | ||
716 | result = scsi_add_host(shost, &intf->dev); | ||
717 | if (result) | ||
718 | goto free; | ||
719 | shost->hostdata[0] = (unsigned long)devinfo; | ||
720 | |||
721 | devinfo->intf = intf; | 727 | devinfo->intf = intf; |
722 | devinfo->udev = udev; | 728 | devinfo->udev = udev; |
723 | uas_configure_endpoints(devinfo); | 729 | uas_configure_endpoints(devinfo); |
724 | 730 | ||
731 | result = scsi_init_shared_tag_map(shost, devinfo->qdepth - 1); | ||
732 | if (result) | ||
733 | goto free; | ||
734 | |||
735 | result = scsi_add_host(shost, &intf->dev); | ||
736 | if (result) | ||
737 | goto deconfig_eps; | ||
738 | |||
739 | shost->hostdata[0] = (unsigned long)devinfo; | ||
740 | |||
725 | scsi_scan_host(shost); | 741 | scsi_scan_host(shost); |
726 | usb_set_intfdata(intf, shost); | 742 | usb_set_intfdata(intf, shost); |
727 | return result; | 743 | return result; |
744 | |||
745 | deconfig_eps: | ||
746 | uas_free_streams(devinfo); | ||
728 | free: | 747 | free: |
729 | kfree(devinfo); | 748 | kfree(devinfo); |
730 | if (shost) | 749 | if (shost) |
@@ -746,18 +765,11 @@ static int uas_post_reset(struct usb_interface *intf) | |||
746 | 765 | ||
747 | static void uas_disconnect(struct usb_interface *intf) | 766 | static void uas_disconnect(struct usb_interface *intf) |
748 | { | 767 | { |
749 | struct usb_device *udev = interface_to_usbdev(intf); | ||
750 | struct usb_host_endpoint *eps[3]; | ||
751 | struct Scsi_Host *shost = usb_get_intfdata(intf); | 768 | struct Scsi_Host *shost = usb_get_intfdata(intf); |
752 | struct uas_dev_info *devinfo = (void *)shost->hostdata[0]; | 769 | struct uas_dev_info *devinfo = (void *)shost->hostdata[0]; |
753 | 770 | ||
754 | scsi_remove_host(shost); | 771 | scsi_remove_host(shost); |
755 | 772 | uas_free_streams(devinfo); | |
756 | eps[0] = usb_pipe_endpoint(udev, devinfo->status_pipe); | ||
757 | eps[1] = usb_pipe_endpoint(udev, devinfo->data_in_pipe); | ||
758 | eps[2] = usb_pipe_endpoint(udev, devinfo->data_out_pipe); | ||
759 | usb_free_streams(intf, eps, 3, GFP_KERNEL); | ||
760 | |||
761 | kfree(devinfo); | 773 | kfree(devinfo); |
762 | } | 774 | } |
763 | 775 | ||