aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/storage
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2013-10-29 05:51:00 -0400
committerSarah Sharp <sarah.a.sharp@linux.intel.com>2014-03-04 18:38:20 -0500
commitb83b86a352280cc8cbbf3760096c703986143b81 (patch)
tree170a36d2084123e9fdd4a019bb43db7c44d4edeb /drivers/usb/storage
parent70cf0fba7625987ef16085f458e3869c6e3043c1 (diff)
uas: Don't allow more then one task to run at the same time
Since we use a fixed tag / stream for tasks we cannot allow more then one to run at the same time. This could happen before this time if a task timed out. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Diffstat (limited to 'drivers/usb/storage')
-rw-r--r--drivers/usb/storage/uas.c39
1 files changed, 34 insertions, 5 deletions
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 9c6f9f9804fd..7fc4ad207752 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -53,6 +53,7 @@ struct uas_dev_info {
53 unsigned cmd_pipe, status_pipe, data_in_pipe, data_out_pipe; 53 unsigned cmd_pipe, status_pipe, data_in_pipe, data_out_pipe;
54 unsigned use_streams:1; 54 unsigned use_streams:1;
55 unsigned uas_sense_old:1; 55 unsigned uas_sense_old:1;
56 unsigned running_task:1;
56 struct scsi_cmnd *cmnd; 57 struct scsi_cmnd *cmnd;
57 spinlock_t lock; 58 spinlock_t lock;
58 struct work_struct work; 59 struct work_struct work;
@@ -195,6 +196,7 @@ static void uas_zap_dead(struct uas_dev_info *devinfo)
195 DATA_OUT_URB_INFLIGHT); 196 DATA_OUT_URB_INFLIGHT);
196 uas_try_complete(cmnd, __func__); 197 uas_try_complete(cmnd, __func__);
197 } 198 }
199 devinfo->running_task = 0;
198 spin_unlock_irqrestore(&devinfo->lock, flags); 200 spin_unlock_irqrestore(&devinfo->lock, flags);
199} 201}
200 202
@@ -340,6 +342,9 @@ static void uas_stat_cmplt(struct urb *urb)
340 342
341 if (!cmnd) { 343 if (!cmnd) {
342 if (iu->iu_id == IU_ID_RESPONSE) { 344 if (iu->iu_id == IU_ID_RESPONSE) {
345 if (!devinfo->running_task)
346 dev_warn(&urb->dev->dev,
347 "stat urb: recv unexpected response iu\n");
343 /* store results for uas_eh_task_mgmt() */ 348 /* store results for uas_eh_task_mgmt() */
344 memcpy(&devinfo->response, iu, sizeof(devinfo->response)); 349 memcpy(&devinfo->response, iu, sizeof(devinfo->response));
345 } 350 }
@@ -726,14 +731,26 @@ static int uas_eh_task_mgmt(struct scsi_cmnd *cmnd,
726 u16 tag = devinfo->qdepth; 731 u16 tag = devinfo->qdepth;
727 unsigned long flags; 732 unsigned long flags;
728 struct urb *sense_urb; 733 struct urb *sense_urb;
734 int result = SUCCESS;
729 735
730 spin_lock_irqsave(&devinfo->lock, flags); 736 spin_lock_irqsave(&devinfo->lock, flags);
737
738 if (devinfo->running_task) {
739 shost_printk(KERN_INFO, shost,
740 "%s: %s: error already running a task\n",
741 __func__, fname);
742 spin_unlock_irqrestore(&devinfo->lock, flags);
743 return FAILED;
744 }
745
746 devinfo->running_task = 1;
731 memset(&devinfo->response, 0, sizeof(devinfo->response)); 747 memset(&devinfo->response, 0, sizeof(devinfo->response));
732 sense_urb = uas_submit_sense_urb(shost, GFP_ATOMIC, tag); 748 sense_urb = uas_submit_sense_urb(shost, GFP_ATOMIC, tag);
733 if (!sense_urb) { 749 if (!sense_urb) {
734 shost_printk(KERN_INFO, shost, 750 shost_printk(KERN_INFO, shost,
735 "%s: %s: submit sense urb failed\n", 751 "%s: %s: submit sense urb failed\n",
736 __func__, fname); 752 __func__, fname);
753 devinfo->running_task = 0;
737 spin_unlock_irqrestore(&devinfo->lock, flags); 754 spin_unlock_irqrestore(&devinfo->lock, flags);
738 return FAILED; 755 return FAILED;
739 } 756 }
@@ -741,6 +758,7 @@ static int uas_eh_task_mgmt(struct scsi_cmnd *cmnd,
741 shost_printk(KERN_INFO, shost, 758 shost_printk(KERN_INFO, shost,
742 "%s: %s: submit task mgmt urb failed\n", 759 "%s: %s: submit task mgmt urb failed\n",
743 __func__, fname); 760 __func__, fname);
761 devinfo->running_task = 0;
744 spin_unlock_irqrestore(&devinfo->lock, flags); 762 spin_unlock_irqrestore(&devinfo->lock, flags);
745 usb_kill_urb(sense_urb); 763 usb_kill_urb(sense_urb);
746 return FAILED; 764 return FAILED;
@@ -748,23 +766,33 @@ static int uas_eh_task_mgmt(struct scsi_cmnd *cmnd,
748 spin_unlock_irqrestore(&devinfo->lock, flags); 766 spin_unlock_irqrestore(&devinfo->lock, flags);
749 767
750 if (usb_wait_anchor_empty_timeout(&devinfo->sense_urbs, 3000) == 0) { 768 if (usb_wait_anchor_empty_timeout(&devinfo->sense_urbs, 3000) == 0) {
769 /*
770 * Note we deliberately do not clear running_task here. If we
771 * allow new tasks to be submitted, there is no way to figure
772 * out if a received response_iu is for the failed task or for
773 * the new one. A bus-reset will eventually clear running_task.
774 */
751 shost_printk(KERN_INFO, shost, 775 shost_printk(KERN_INFO, shost,
752 "%s: %s timed out\n", __func__, fname); 776 "%s: %s timed out\n", __func__, fname);
753 return FAILED; 777 return FAILED;
754 } 778 }
779
780 spin_lock_irqsave(&devinfo->lock, flags);
781 devinfo->running_task = 0;
755 if (be16_to_cpu(devinfo->response.tag) != tag) { 782 if (be16_to_cpu(devinfo->response.tag) != tag) {
756 shost_printk(KERN_INFO, shost, 783 shost_printk(KERN_INFO, shost,
757 "%s: %s failed (wrong tag %d/%d)\n", __func__, 784 "%s: %s failed (wrong tag %d/%d)\n", __func__,
758 fname, be16_to_cpu(devinfo->response.tag), tag); 785 fname, be16_to_cpu(devinfo->response.tag), tag);
759 return FAILED; 786 result = FAILED;
760 } 787 } else if (devinfo->response.response_code != RC_TMF_COMPLETE) {
761 if (devinfo->response.response_code != RC_TMF_COMPLETE) {
762 shost_printk(KERN_INFO, shost, 788 shost_printk(KERN_INFO, shost,
763 "%s: %s failed (rc 0x%x)\n", __func__, 789 "%s: %s failed (rc 0x%x)\n", __func__,
764 fname, devinfo->response.response_code); 790 fname, devinfo->response.response_code);
765 return FAILED; 791 result = FAILED;
766 } 792 }
767 return SUCCESS; 793 spin_unlock_irqrestore(&devinfo->lock, flags);
794
795 return result;
768} 796}
769 797
770static int uas_eh_abort_handler(struct scsi_cmnd *cmnd) 798static int uas_eh_abort_handler(struct scsi_cmnd *cmnd)
@@ -982,6 +1010,7 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id)
982 devinfo->intf = intf; 1010 devinfo->intf = intf;
983 devinfo->udev = udev; 1011 devinfo->udev = udev;
984 devinfo->resetting = 0; 1012 devinfo->resetting = 0;
1013 devinfo->running_task = 0;
985 init_usb_anchor(&devinfo->cmd_urbs); 1014 init_usb_anchor(&devinfo->cmd_urbs);
986 init_usb_anchor(&devinfo->sense_urbs); 1015 init_usb_anchor(&devinfo->sense_urbs);
987 init_usb_anchor(&devinfo->data_urbs); 1016 init_usb_anchor(&devinfo->data_urbs);