aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/storage/uas.c
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2012-06-19 03:54:49 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-06-25 14:50:59 -0400
commitdb32de11f75673c2a0f2651ae58b0f25b8c5b0eb (patch)
tree06c96018028813e1cad1d96e7feb96dae81a7648 /drivers/usb/storage/uas.c
parentc621a81edecdee85da32c566c21836332c764fda (diff)
Revert "usb/uas: one only one status URB/host on stream-less connection"
This reverts commit ceb3f91fd53c9fbd7b292fc2754ba4efffeeeedb. IMO the real bug is assigning status urbs to scsi requests. First there is no such link in the non-stream case. Also there isn't nessesarely a scsi request in the first place, for example when submitting task management requests. This patch just papers over the real bug and introduces different status urb handling in the stream/non-stream case for no good reason. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/storage/uas.c')
-rw-r--r--drivers/usb/storage/uas.c70
1 files changed, 10 insertions, 60 deletions
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index f98ba40352c1..36279a46fd27 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -46,7 +46,6 @@ struct uas_dev_info {
46 unsigned use_streams:1; 46 unsigned use_streams:1;
47 unsigned uas_sense_old:1; 47 unsigned uas_sense_old:1;
48 struct scsi_cmnd *cmnd; 48 struct scsi_cmnd *cmnd;
49 struct urb *status_urb; /* used only if stream support is available */
50}; 49};
51 50
52enum { 51enum {
@@ -65,7 +64,6 @@ struct uas_cmd_info {
65 unsigned int state; 64 unsigned int state;
66 unsigned int stream; 65 unsigned int stream;
67 struct urb *cmd_urb; 66 struct urb *cmd_urb;
68 /* status_urb is used only if stream support isn't available */
69 struct urb *status_urb; 67 struct urb *status_urb;
70 struct urb *data_in_urb; 68 struct urb *data_in_urb;
71 struct urb *data_out_urb; 69 struct urb *data_out_urb;
@@ -129,6 +127,7 @@ static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd)
129 127
130 cmnd->result = sense_iu->status; 128 cmnd->result = sense_iu->status;
131 cmnd->scsi_done(cmnd); 129 cmnd->scsi_done(cmnd);
130 usb_free_urb(urb);
132} 131}
133 132
134static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd) 133static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd)
@@ -153,6 +152,7 @@ static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd)
153 152
154 cmnd->result = sense_iu->status; 153 cmnd->result = sense_iu->status;
155 cmnd->scsi_done(cmnd); 154 cmnd->scsi_done(cmnd);
155 usb_free_urb(urb);
156} 156}
157 157
158static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd, 158static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd,
@@ -161,7 +161,7 @@ static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd,
161 struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; 161 struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
162 int err; 162 int err;
163 163
164 cmdinfo->state = direction; 164 cmdinfo->state = direction | SUBMIT_STATUS_URB;
165 err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC); 165 err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC);
166 if (err) { 166 if (err) {
167 spin_lock(&uas_work_lock); 167 spin_lock(&uas_work_lock);
@@ -178,12 +178,10 @@ static void uas_stat_cmplt(struct urb *urb)
178 struct uas_dev_info *devinfo = (void *)shost->hostdata[0]; 178 struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
179 struct scsi_cmnd *cmnd; 179 struct scsi_cmnd *cmnd;
180 u16 tag; 180 u16 tag;
181 int ret;
182 181
183 if (urb->status) { 182 if (urb->status) {
184 dev_err(&urb->dev->dev, "URB BAD STATUS %d\n", urb->status); 183 dev_err(&urb->dev->dev, "URB BAD STATUS %d\n", urb->status);
185 if (devinfo->use_streams) 184 usb_free_urb(urb);
186 usb_free_urb(urb);
187 return; 185 return;
188 } 186 }
189 187
@@ -193,13 +191,7 @@ static void uas_stat_cmplt(struct urb *urb)
193 else 191 else
194 cmnd = scsi_host_find_tag(shost, tag - 1); 192 cmnd = scsi_host_find_tag(shost, tag - 1);
195 if (!cmnd) { 193 if (!cmnd) {
196 if (devinfo->use_streams) { 194 usb_free_urb(urb);
197 usb_free_urb(urb);
198 return;
199 }
200 ret = usb_submit_urb(urb, GFP_ATOMIC);
201 if (ret)
202 dev_err(&urb->dev->dev, "failed submit status urb\n");
203 return; 195 return;
204 } 196 }
205 197
@@ -225,15 +217,6 @@ static void uas_stat_cmplt(struct urb *urb)
225 scmd_printk(KERN_ERR, cmnd, 217 scmd_printk(KERN_ERR, cmnd,
226 "Bogus IU (%d) received on status pipe\n", iu->iu_id); 218 "Bogus IU (%d) received on status pipe\n", iu->iu_id);
227 } 219 }
228
229 if (devinfo->use_streams) {
230 usb_free_urb(urb);
231 return;
232 }
233
234 ret = usb_submit_urb(urb, GFP_ATOMIC);
235 if (ret)
236 dev_err(&urb->dev->dev, "failed submit status urb\n");
237} 220}
238 221
239static void uas_data_cmplt(struct urb *urb) 222static void uas_data_cmplt(struct urb *urb)
@@ -264,7 +247,7 @@ static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp,
264} 247}
265 248
266static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp, 249static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp,
267 struct Scsi_Host *shost, u16 stream_id) 250 struct scsi_cmnd *cmnd, u16 stream_id)
268{ 251{
269 struct usb_device *udev = devinfo->udev; 252 struct usb_device *udev = devinfo->udev;
270 struct urb *urb = usb_alloc_urb(0, gfp); 253 struct urb *urb = usb_alloc_urb(0, gfp);
@@ -278,7 +261,7 @@ static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp,
278 goto free; 261 goto free;
279 262
280 usb_fill_bulk_urb(urb, udev, devinfo->status_pipe, iu, sizeof(*iu), 263 usb_fill_bulk_urb(urb, udev, devinfo->status_pipe, iu, sizeof(*iu),
281 uas_stat_cmplt, shost); 264 uas_stat_cmplt, cmnd->device->host);
282 urb->stream_id = stream_id; 265 urb->stream_id = stream_id;
283 urb->transfer_flags |= URB_FREE_BUFFER; 266 urb->transfer_flags |= URB_FREE_BUFFER;
284 out: 267 out:
@@ -340,8 +323,8 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
340 struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; 323 struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
341 324
342 if (cmdinfo->state & ALLOC_STATUS_URB) { 325 if (cmdinfo->state & ALLOC_STATUS_URB) {
343 cmdinfo->status_urb = uas_alloc_sense_urb(devinfo, gfp, 326 cmdinfo->status_urb = uas_alloc_sense_urb(devinfo, gfp, cmnd,
344 cmnd->device->host, cmdinfo->stream); 327 cmdinfo->stream);
345 if (!cmdinfo->status_urb) 328 if (!cmdinfo->status_urb)
346 return SCSI_MLQUEUE_DEVICE_BUSY; 329 return SCSI_MLQUEUE_DEVICE_BUSY;
347 cmdinfo->state &= ~ALLOC_STATUS_URB; 330 cmdinfo->state &= ~ALLOC_STATUS_URB;
@@ -450,8 +433,7 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
450 } 433 }
451 434
452 if (!devinfo->use_streams) { 435 if (!devinfo->use_streams) {
453 cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB | 436 cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB);
454 ALLOC_STATUS_URB | SUBMIT_STATUS_URB);
455 cmdinfo->stream = 0; 437 cmdinfo->stream = 0;
456 } 438 }
457 439
@@ -662,29 +644,6 @@ static void uas_configure_endpoints(struct uas_dev_info *devinfo)
662 } 644 }
663} 645}
664 646
665static int uas_alloc_status_urb(struct uas_dev_info *devinfo,
666 struct Scsi_Host *shost)
667{
668 if (devinfo->use_streams) {
669 devinfo->status_urb = NULL;
670 return 0;
671 }
672
673 devinfo->status_urb = uas_alloc_sense_urb(devinfo, GFP_KERNEL,
674 shost, 0);
675 if (!devinfo->status_urb)
676 goto err_s_urb;
677
678 if (usb_submit_urb(devinfo->status_urb, GFP_KERNEL))
679 goto err_submit_urb;
680
681 return 0;
682err_submit_urb:
683 usb_free_urb(devinfo->status_urb);
684err_s_urb:
685 return -ENOMEM;
686}
687
688static void uas_free_streams(struct uas_dev_info *devinfo) 647static void uas_free_streams(struct uas_dev_info *devinfo)
689{ 648{
690 struct usb_device *udev = devinfo->udev; 649 struct usb_device *udev = devinfo->udev;
@@ -739,17 +698,10 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id)
739 698
740 shost->hostdata[0] = (unsigned long)devinfo; 699 shost->hostdata[0] = (unsigned long)devinfo;
741 700
742 result = uas_alloc_status_urb(devinfo, shost);
743 if (result)
744 goto err_alloc_status;
745
746 scsi_scan_host(shost); 701 scsi_scan_host(shost);
747 usb_set_intfdata(intf, shost); 702 usb_set_intfdata(intf, shost);
748 return result; 703 return result;
749 704
750err_alloc_status:
751 scsi_remove_host(shost);
752 shost = NULL;
753deconfig_eps: 705deconfig_eps:
754 uas_free_streams(devinfo); 706 uas_free_streams(devinfo);
755 free: 707 free:
@@ -777,8 +729,6 @@ static void uas_disconnect(struct usb_interface *intf)
777 struct uas_dev_info *devinfo = (void *)shost->hostdata[0]; 729 struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
778 730
779 scsi_remove_host(shost); 731 scsi_remove_host(shost);
780 usb_kill_urb(devinfo->status_urb);
781 usb_free_urb(devinfo->status_urb);
782 uas_free_streams(devinfo); 732 uas_free_streams(devinfo);
783 kfree(devinfo); 733 kfree(devinfo);
784} 734}