aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/storage/uas.c
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2012-02-02 17:47:14 -0500
committerSarah Sharp <sarah.a.sharp@linux.intel.com>2012-02-02 17:47:14 -0500
commitb603669842b3b2c66a1fc2e926f35a2143be8b3b (patch)
tree8b924819815197c04c2cc2ca6b514391ce170633 /drivers/usb/storage/uas.c
parentfec67b45bf045582c3172101970090d640cd56d9 (diff)
parentceb3f91fd53c9fbd7b292fc2754ba4efffeeeedb (diff)
Merge tag 'uas_for_sarah' of git://linutronix.de/users/bigeasy/linux into for-uas-next
Merge UAS bug fixes from Sebastian Andrzej Siewior, including some patches of mine that he signed. UAS fixes for Sarah
Diffstat (limited to 'drivers/usb/storage/uas.c')
-rw-r--r--drivers/usb/storage/uas.c157
1 files changed, 117 insertions, 40 deletions
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index a33ead5dce20..e0133c9ab0bf 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -98,6 +98,8 @@ struct uas_dev_info {
98 unsigned cmd_pipe, status_pipe, data_in_pipe, data_out_pipe; 98 unsigned cmd_pipe, status_pipe, data_in_pipe, data_out_pipe;
99 unsigned use_streams:1; 99 unsigned use_streams:1;
100 unsigned uas_sense_old:1; 100 unsigned uas_sense_old:1;
101 struct scsi_cmnd *cmnd;
102 struct urb *status_urb; /* used only if stream support is available */
101}; 103};
102 104
103enum { 105enum {
@@ -116,6 +118,7 @@ struct uas_cmd_info {
116 unsigned int state; 118 unsigned int state;
117 unsigned int stream; 119 unsigned int stream;
118 struct urb *cmd_urb; 120 struct urb *cmd_urb;
121 /* status_urb is used only if stream support isn't available */
119 struct urb *status_urb; 122 struct urb *status_urb;
120 struct urb *data_in_urb; 123 struct urb *data_in_urb;
121 struct urb *data_out_urb; 124 struct urb *data_out_urb;
@@ -125,29 +128,38 @@ struct uas_cmd_info {
125/* I hate forward declarations, but I actually have a loop */ 128/* I hate forward declarations, but I actually have a loop */
126static int uas_submit_urbs(struct scsi_cmnd *cmnd, 129static int uas_submit_urbs(struct scsi_cmnd *cmnd,
127 struct uas_dev_info *devinfo, gfp_t gfp); 130 struct uas_dev_info *devinfo, gfp_t gfp);
131static void uas_do_work(struct work_struct *work);
128 132
133static DECLARE_WORK(uas_work, uas_do_work);
129static DEFINE_SPINLOCK(uas_work_lock); 134static DEFINE_SPINLOCK(uas_work_lock);
130static LIST_HEAD(uas_work_list); 135static LIST_HEAD(uas_work_list);
131 136
132static void uas_do_work(struct work_struct *work) 137static void uas_do_work(struct work_struct *work)
133{ 138{
134 struct uas_cmd_info *cmdinfo; 139 struct uas_cmd_info *cmdinfo;
140 struct uas_cmd_info *temp;
135 struct list_head list; 141 struct list_head list;
142 int err;
136 143
137 spin_lock_irq(&uas_work_lock); 144 spin_lock_irq(&uas_work_lock);
138 list_replace_init(&uas_work_list, &list); 145 list_replace_init(&uas_work_list, &list);
139 spin_unlock_irq(&uas_work_lock); 146 spin_unlock_irq(&uas_work_lock);
140 147
141 list_for_each_entry(cmdinfo, &list, list) { 148 list_for_each_entry_safe(cmdinfo, temp, &list, list) {
142 struct scsi_pointer *scp = (void *)cmdinfo; 149 struct scsi_pointer *scp = (void *)cmdinfo;
143 struct scsi_cmnd *cmnd = container_of(scp, 150 struct scsi_cmnd *cmnd = container_of(scp,
144 struct scsi_cmnd, SCp); 151 struct scsi_cmnd, SCp);
145 uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_NOIO); 152 err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_NOIO);
153 if (err) {
154 list_del(&cmdinfo->list);
155 spin_lock_irq(&uas_work_lock);
156 list_add_tail(&cmdinfo->list, &uas_work_list);
157 spin_unlock_irq(&uas_work_lock);
158 schedule_work(&uas_work);
159 }
146 } 160 }
147} 161}
148 162
149static DECLARE_WORK(uas_work, uas_do_work);
150
151static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd) 163static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd)
152{ 164{
153 struct sense_iu *sense_iu = urb->transfer_buffer; 165 struct sense_iu *sense_iu = urb->transfer_buffer;
@@ -169,10 +181,7 @@ static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd)
169 } 181 }
170 182
171 cmnd->result = sense_iu->status; 183 cmnd->result = sense_iu->status;
172 if (sdev->current_cmnd)
173 sdev->current_cmnd = NULL;
174 cmnd->scsi_done(cmnd); 184 cmnd->scsi_done(cmnd);
175 usb_free_urb(urb);
176} 185}
177 186
178static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd) 187static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd)
@@ -196,10 +205,7 @@ static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd)
196 } 205 }
197 206
198 cmnd->result = sense_iu->status; 207 cmnd->result = sense_iu->status;
199 if (sdev->current_cmnd)
200 sdev->current_cmnd = NULL;
201 cmnd->scsi_done(cmnd); 208 cmnd->scsi_done(cmnd);
202 usb_free_urb(urb);
203} 209}
204 210
205static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd, 211static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd,
@@ -208,7 +214,7 @@ static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd,
208 struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; 214 struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
209 int err; 215 int err;
210 216
211 cmdinfo->state = direction | SUBMIT_STATUS_URB; 217 cmdinfo->state = direction;
212 err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC); 218 err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC);
213 if (err) { 219 if (err) {
214 spin_lock(&uas_work_lock); 220 spin_lock(&uas_work_lock);
@@ -221,27 +227,40 @@ static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd,
221static void uas_stat_cmplt(struct urb *urb) 227static void uas_stat_cmplt(struct urb *urb)
222{ 228{
223 struct iu *iu = urb->transfer_buffer; 229 struct iu *iu = urb->transfer_buffer;
224 struct scsi_device *sdev = urb->context; 230 struct Scsi_Host *shost = urb->context;
225 struct uas_dev_info *devinfo = sdev->hostdata; 231 struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
226 struct scsi_cmnd *cmnd; 232 struct scsi_cmnd *cmnd;
227 u16 tag; 233 u16 tag;
234 int ret;
228 235
229 if (urb->status) { 236 if (urb->status) {
230 dev_err(&urb->dev->dev, "URB BAD STATUS %d\n", urb->status); 237 dev_err(&urb->dev->dev, "URB BAD STATUS %d\n", urb->status);
231 usb_free_urb(urb); 238 if (devinfo->use_streams)
239 usb_free_urb(urb);
232 return; 240 return;
233 } 241 }
234 242
235 tag = be16_to_cpup(&iu->tag) - 1; 243 tag = be16_to_cpup(&iu->tag) - 1;
236 if (sdev->current_cmnd) 244 if (tag == 0)
237 cmnd = sdev->current_cmnd; 245 cmnd = devinfo->cmnd;
238 else 246 else
239 cmnd = scsi_find_tag(sdev, tag); 247 cmnd = scsi_host_find_tag(shost, tag - 1);
240 if (!cmnd) 248 if (!cmnd) {
249 if (devinfo->use_streams) {
250 usb_free_urb(urb);
251 return;
252 }
253 ret = usb_submit_urb(urb, GFP_ATOMIC);
254 if (ret)
255 dev_err(&urb->dev->dev, "failed submit status urb\n");
241 return; 256 return;
257 }
242 258
243 switch (iu->iu_id) { 259 switch (iu->iu_id) {
244 case IU_ID_STATUS: 260 case IU_ID_STATUS:
261 if (devinfo->cmnd == cmnd)
262 devinfo->cmnd = NULL;
263
245 if (urb->actual_length < 16) 264 if (urb->actual_length < 16)
246 devinfo->uas_sense_old = 1; 265 devinfo->uas_sense_old = 1;
247 if (devinfo->uas_sense_old) 266 if (devinfo->uas_sense_old)
@@ -259,6 +278,15 @@ static void uas_stat_cmplt(struct urb *urb)
259 scmd_printk(KERN_ERR, cmnd, 278 scmd_printk(KERN_ERR, cmnd,
260 "Bogus IU (%d) received on status pipe\n", iu->iu_id); 279 "Bogus IU (%d) received on status pipe\n", iu->iu_id);
261 } 280 }
281
282 if (devinfo->use_streams) {
283 usb_free_urb(urb);
284 return;
285 }
286
287 ret = usb_submit_urb(urb, GFP_ATOMIC);
288 if (ret)
289 dev_err(&urb->dev->dev, "failed submit status urb\n");
262} 290}
263 291
264static void uas_data_cmplt(struct urb *urb) 292static void uas_data_cmplt(struct urb *urb)
@@ -289,7 +317,7 @@ static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp,
289} 317}
290 318
291static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp, 319static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp,
292 struct scsi_cmnd *cmnd, u16 stream_id) 320 struct Scsi_Host *shost, u16 stream_id)
293{ 321{
294 struct usb_device *udev = devinfo->udev; 322 struct usb_device *udev = devinfo->udev;
295 struct urb *urb = usb_alloc_urb(0, gfp); 323 struct urb *urb = usb_alloc_urb(0, gfp);
@@ -303,7 +331,7 @@ static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp,
303 goto free; 331 goto free;
304 332
305 usb_fill_bulk_urb(urb, udev, devinfo->status_pipe, iu, sizeof(*iu), 333 usb_fill_bulk_urb(urb, udev, devinfo->status_pipe, iu, sizeof(*iu),
306 uas_stat_cmplt, cmnd->device); 334 uas_stat_cmplt, shost);
307 urb->stream_id = stream_id; 335 urb->stream_id = stream_id;
308 urb->transfer_flags |= URB_FREE_BUFFER; 336 urb->transfer_flags |= URB_FREE_BUFFER;
309 out: 337 out:
@@ -334,7 +362,10 @@ static struct urb *uas_alloc_cmd_urb(struct uas_dev_info *devinfo, gfp_t gfp,
334 goto free; 362 goto free;
335 363
336 iu->iu_id = IU_ID_COMMAND; 364 iu->iu_id = IU_ID_COMMAND;
337 iu->tag = cpu_to_be16(stream_id); 365 if (blk_rq_tagged(cmnd->request))
366 iu->tag = cpu_to_be16(cmnd->request->tag + 2);
367 else
368 iu->tag = cpu_to_be16(1);
338 iu->prio_attr = UAS_SIMPLE_TAG; 369 iu->prio_attr = UAS_SIMPLE_TAG;
339 iu->len = len; 370 iu->len = len;
340 int_to_scsilun(sdev->lun, &iu->lun); 371 int_to_scsilun(sdev->lun, &iu->lun);
@@ -362,8 +393,8 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
362 struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; 393 struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
363 394
364 if (cmdinfo->state & ALLOC_STATUS_URB) { 395 if (cmdinfo->state & ALLOC_STATUS_URB) {
365 cmdinfo->status_urb = uas_alloc_sense_urb(devinfo, gfp, cmnd, 396 cmdinfo->status_urb = uas_alloc_sense_urb(devinfo, gfp,
366 cmdinfo->stream); 397 cmnd->device->host, cmdinfo->stream);
367 if (!cmdinfo->status_urb) 398 if (!cmdinfo->status_urb)
368 return SCSI_MLQUEUE_DEVICE_BUSY; 399 return SCSI_MLQUEUE_DEVICE_BUSY;
369 cmdinfo->state &= ~ALLOC_STATUS_URB; 400 cmdinfo->state &= ~ALLOC_STATUS_URB;
@@ -444,13 +475,13 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
444 475
445 BUILD_BUG_ON(sizeof(struct uas_cmd_info) > sizeof(struct scsi_pointer)); 476 BUILD_BUG_ON(sizeof(struct uas_cmd_info) > sizeof(struct scsi_pointer));
446 477
447 if (!cmdinfo->status_urb && sdev->current_cmnd) 478 if (devinfo->cmnd)
448 return SCSI_MLQUEUE_DEVICE_BUSY; 479 return SCSI_MLQUEUE_DEVICE_BUSY;
449 480
450 if (blk_rq_tagged(cmnd->request)) { 481 if (blk_rq_tagged(cmnd->request)) {
451 cmdinfo->stream = cmnd->request->tag + 1; 482 cmdinfo->stream = cmnd->request->tag + 2;
452 } else { 483 } else {
453 sdev->current_cmnd = cmnd; 484 devinfo->cmnd = cmnd;
454 cmdinfo->stream = 1; 485 cmdinfo->stream = 1;
455 } 486 }
456 487
@@ -472,7 +503,8 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
472 } 503 }
473 504
474 if (!devinfo->use_streams) { 505 if (!devinfo->use_streams) {
475 cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB); 506 cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB |
507 ALLOC_STATUS_URB | SUBMIT_STATUS_URB);
476 cmdinfo->stream = 0; 508 cmdinfo->stream = 0;
477 } 509 }
478 510
@@ -551,7 +583,7 @@ static int uas_slave_configure(struct scsi_device *sdev)
551{ 583{
552 struct uas_dev_info *devinfo = sdev->hostdata; 584 struct uas_dev_info *devinfo = sdev->hostdata;
553 scsi_set_tag_type(sdev, MSG_ORDERED_TAG); 585 scsi_set_tag_type(sdev, MSG_ORDERED_TAG);
554 scsi_activate_tcq(sdev, devinfo->qdepth - 1); 586 scsi_activate_tcq(sdev, devinfo->qdepth - 2);
555 return 0; 587 return 0;
556} 588}
557 589
@@ -619,6 +651,7 @@ static void uas_configure_endpoints(struct uas_dev_info *devinfo)
619 unsigned i, n_endpoints = intf->cur_altsetting->desc.bNumEndpoints; 651 unsigned i, n_endpoints = intf->cur_altsetting->desc.bNumEndpoints;
620 652
621 devinfo->uas_sense_old = 0; 653 devinfo->uas_sense_old = 0;
654 devinfo->cmnd = NULL;
622 655
623 for (i = 0; i < n_endpoints; i++) { 656 for (i = 0; i < n_endpoints; i++) {
624 unsigned char *extra = endpoint[i].extra; 657 unsigned char *extra = endpoint[i].extra;
@@ -670,6 +703,40 @@ static void uas_configure_endpoints(struct uas_dev_info *devinfo)
670 } 703 }
671} 704}
672 705
706static int uas_alloc_status_urb(struct uas_dev_info *devinfo,
707 struct Scsi_Host *shost)
708{
709 if (devinfo->use_streams) {
710 devinfo->status_urb = NULL;
711 return 0;
712 }
713
714 devinfo->status_urb = uas_alloc_sense_urb(devinfo, GFP_KERNEL,
715 shost, 0);
716 if (!devinfo->status_urb)
717 goto err_s_urb;
718
719 if (usb_submit_urb(devinfo->status_urb, GFP_KERNEL))
720 goto err_submit_urb;
721
722 return 0;
723err_submit_urb:
724 usb_free_urb(devinfo->status_urb);
725err_s_urb:
726 return -ENOMEM;
727}
728
729static void uas_free_streams(struct uas_dev_info *devinfo)
730{
731 struct usb_device *udev = devinfo->udev;
732 struct usb_host_endpoint *eps[3];
733
734 eps[0] = usb_pipe_endpoint(udev, devinfo->status_pipe);
735 eps[1] = usb_pipe_endpoint(udev, devinfo->data_in_pipe);
736 eps[2] = usb_pipe_endpoint(udev, devinfo->data_out_pipe);
737 usb_free_streams(devinfo->intf, eps, 3, GFP_KERNEL);
738}
739
673/* 740/*
674 * XXX: What I'd like to do here is register a SCSI host for each USB host in 741 * XXX: What I'd like to do here is register a SCSI host for each USB host in
675 * the system. Follow usb-storage's design of registering a SCSI host for 742 * the system. Follow usb-storage's design of registering a SCSI host for
@@ -699,18 +766,33 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id)
699 shost->max_id = 1; 766 shost->max_id = 1;
700 shost->sg_tablesize = udev->bus->sg_tablesize; 767 shost->sg_tablesize = udev->bus->sg_tablesize;
701 768
702 result = scsi_add_host(shost, &intf->dev); 769 devinfo->intf = intf;
770 devinfo->udev = udev;
771 uas_configure_endpoints(devinfo);
772
773 result = scsi_init_shared_tag_map(shost, devinfo->qdepth - 2);
703 if (result) 774 if (result)
704 goto free; 775 goto free;
776
777 result = scsi_add_host(shost, &intf->dev);
778 if (result)
779 goto deconfig_eps;
780
705 shost->hostdata[0] = (unsigned long)devinfo; 781 shost->hostdata[0] = (unsigned long)devinfo;
706 782
707 devinfo->intf = intf; 783 result = uas_alloc_status_urb(devinfo, shost);
708 devinfo->udev = udev; 784 if (result)
709 uas_configure_endpoints(devinfo); 785 goto err_alloc_status;
710 786
711 scsi_scan_host(shost); 787 scsi_scan_host(shost);
712 usb_set_intfdata(intf, shost); 788 usb_set_intfdata(intf, shost);
713 return result; 789 return result;
790
791err_alloc_status:
792 scsi_remove_host(shost);
793 shost = NULL;
794deconfig_eps:
795 uas_free_streams(devinfo);
714 free: 796 free:
715 kfree(devinfo); 797 kfree(devinfo);
716 if (shost) 798 if (shost)
@@ -732,18 +814,13 @@ static int uas_post_reset(struct usb_interface *intf)
732 814
733static void uas_disconnect(struct usb_interface *intf) 815static void uas_disconnect(struct usb_interface *intf)
734{ 816{
735 struct usb_device *udev = interface_to_usbdev(intf);
736 struct usb_host_endpoint *eps[3];
737 struct Scsi_Host *shost = usb_get_intfdata(intf); 817 struct Scsi_Host *shost = usb_get_intfdata(intf);
738 struct uas_dev_info *devinfo = (void *)shost->hostdata[0]; 818 struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
739 819
740 scsi_remove_host(shost); 820 scsi_remove_host(shost);
741 821 usb_kill_urb(devinfo->status_urb);
742 eps[0] = usb_pipe_endpoint(udev, devinfo->status_pipe); 822 usb_free_urb(devinfo->status_urb);
743 eps[1] = usb_pipe_endpoint(udev, devinfo->data_in_pipe); 823 uas_free_streams(devinfo);
744 eps[2] = usb_pipe_endpoint(udev, devinfo->data_out_pipe);
745 usb_free_streams(intf, eps, 3, GFP_KERNEL);
746
747 kfree(devinfo); 824 kfree(devinfo);
748} 825}
749 826