diff options
author | Gerd Hoffmann <kraxel@redhat.com> | 2012-06-19 03:54:49 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-06-25 14:50:59 -0400 |
commit | db32de11f75673c2a0f2651ae58b0f25b8c5b0eb (patch) | |
tree | 06c96018028813e1cad1d96e7feb96dae81a7648 /drivers/usb/storage/uas.c | |
parent | c621a81edecdee85da32c566c21836332c764fda (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.c | 70 |
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 | ||
52 | enum { | 51 | enum { |
@@ -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 | ||
134 | static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd) | 133 | static 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 | ||
158 | static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd, | 158 | static 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 | ||
239 | static void uas_data_cmplt(struct urb *urb) | 222 | static 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 | ||
266 | static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp, | 249 | static 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 | ||
665 | static 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; | ||
682 | err_submit_urb: | ||
683 | usb_free_urb(devinfo->status_urb); | ||
684 | err_s_urb: | ||
685 | return -ENOMEM; | ||
686 | } | ||
687 | |||
688 | static void uas_free_streams(struct uas_dev_info *devinfo) | 647 | static 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 | ||
750 | err_alloc_status: | ||
751 | scsi_remove_host(shost); | ||
752 | shost = NULL; | ||
753 | deconfig_eps: | 705 | deconfig_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 | } |