Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+118 -41
+118 -41
drivers/usb/storage/uas.c
··· 98 98 unsigned cmd_pipe, status_pipe, data_in_pipe, data_out_pipe; 99 99 unsigned use_streams:1; 100 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 103 105 enum { ··· 118 116 unsigned int state; 119 117 unsigned int stream; 120 118 struct urb *cmd_urb; 119 + /* status_urb is used only if stream support isn't available */ 121 120 struct urb *status_urb; 122 121 struct urb *data_in_urb; 123 122 struct urb *data_out_urb; ··· 128 125 /* I hate forward declarations, but I actually have a loop */ 129 126 static int uas_submit_urbs(struct scsi_cmnd *cmnd, 130 127 struct uas_dev_info *devinfo, gfp_t gfp); 128 + static void uas_do_work(struct work_struct *work); 131 129 130 + static DECLARE_WORK(uas_work, uas_do_work); 132 131 static DEFINE_SPINLOCK(uas_work_lock); 133 132 static LIST_HEAD(uas_work_list); 134 133 135 134 static void uas_do_work(struct work_struct *work) 136 135 { 137 136 struct uas_cmd_info *cmdinfo; 137 + struct uas_cmd_info *temp; 138 138 struct list_head list; 139 + int err; 139 140 140 141 spin_lock_irq(&uas_work_lock); 141 142 list_replace_init(&uas_work_list, &list); 142 143 spin_unlock_irq(&uas_work_lock); 143 144 144 - list_for_each_entry(cmdinfo, &list, list) { 145 + list_for_each_entry_safe(cmdinfo, temp, &list, list) { 145 146 struct scsi_pointer *scp = (void *)cmdinfo; 146 147 struct scsi_cmnd *cmnd = container_of(scp, 147 148 struct scsi_cmnd, SCp); 148 - uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_NOIO); 149 + err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_NOIO); 150 + if (err) { 151 + list_del(&cmdinfo->list); 152 + spin_lock_irq(&uas_work_lock); 153 + list_add_tail(&cmdinfo->list, &uas_work_list); 154 + spin_unlock_irq(&uas_work_lock); 155 + schedule_work(&uas_work); 156 + } 149 157 } 150 158 } 151 - 152 - static DECLARE_WORK(uas_work, uas_do_work); 153 159 154 160 static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd) 155 161 { ··· 181 169 } 182 170 183 171 cmnd->result = sense_iu->status; 184 - if (sdev->current_cmnd) 185 - sdev->current_cmnd = NULL; 186 172 cmnd->scsi_done(cmnd); 187 - usb_free_urb(urb); 188 173 } 189 174 190 175 static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd) ··· 205 196 } 206 197 207 198 cmnd->result = sense_iu->status; 208 - if (sdev->current_cmnd) 209 - sdev->current_cmnd = NULL; 210 199 cmnd->scsi_done(cmnd); 211 - usb_free_urb(urb); 212 200 } 213 201 214 202 static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd, ··· 214 208 struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; 215 209 int err; 216 210 217 - cmdinfo->state = direction | SUBMIT_STATUS_URB; 211 + cmdinfo->state = direction; 218 212 err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC); 219 213 if (err) { 220 214 spin_lock(&uas_work_lock); ··· 227 221 static void uas_stat_cmplt(struct urb *urb) 228 222 { 229 223 struct iu *iu = urb->transfer_buffer; 230 - struct scsi_device *sdev = urb->context; 231 - struct uas_dev_info *devinfo = sdev->hostdata; 224 + struct Scsi_Host *shost = urb->context; 225 + struct uas_dev_info *devinfo = (void *)shost->hostdata[0]; 232 226 struct scsi_cmnd *cmnd; 233 227 u16 tag; 228 + int ret; 234 229 235 230 if (urb->status) { 236 231 dev_err(&urb->dev->dev, "URB BAD STATUS %d\n", urb->status); 237 - usb_free_urb(urb); 232 + if (devinfo->use_streams) 233 + usb_free_urb(urb); 238 234 return; 239 235 } 240 236 241 237 tag = be16_to_cpup(&iu->tag) - 1; 242 - if (sdev->current_cmnd) 243 - cmnd = sdev->current_cmnd; 238 + if (tag == 0) 239 + cmnd = devinfo->cmnd; 244 240 else 245 - cmnd = scsi_find_tag(sdev, tag); 246 - if (!cmnd) 241 + cmnd = scsi_host_find_tag(shost, tag - 1); 242 + if (!cmnd) { 243 + if (devinfo->use_streams) { 244 + usb_free_urb(urb); 245 + return; 246 + } 247 + ret = usb_submit_urb(urb, GFP_ATOMIC); 248 + if (ret) 249 + dev_err(&urb->dev->dev, "failed submit status urb\n"); 247 250 return; 251 + } 248 252 249 253 switch (iu->iu_id) { 250 254 case IU_ID_STATUS: 255 + if (devinfo->cmnd == cmnd) 256 + devinfo->cmnd = NULL; 257 + 251 258 if (urb->actual_length < 16) 252 259 devinfo->uas_sense_old = 1; 253 260 if (devinfo->uas_sense_old) ··· 278 259 scmd_printk(KERN_ERR, cmnd, 279 260 "Bogus IU (%d) received on status pipe\n", iu->iu_id); 280 261 } 262 + 263 + if (devinfo->use_streams) { 264 + usb_free_urb(urb); 265 + return; 266 + } 267 + 268 + ret = usb_submit_urb(urb, GFP_ATOMIC); 269 + if (ret) 270 + dev_err(&urb->dev->dev, "failed submit status urb\n"); 281 271 } 282 272 283 273 static void uas_data_cmplt(struct urb *urb) ··· 317 289 } 318 290 319 291 static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp, 320 - struct scsi_cmnd *cmnd, u16 stream_id) 292 + struct Scsi_Host *shost, u16 stream_id) 321 293 { 322 294 struct usb_device *udev = devinfo->udev; 323 295 struct urb *urb = usb_alloc_urb(0, gfp); ··· 331 303 goto free; 332 304 333 305 usb_fill_bulk_urb(urb, udev, devinfo->status_pipe, iu, sizeof(*iu), 334 - uas_stat_cmplt, cmnd->device); 306 + uas_stat_cmplt, shost); 335 307 urb->stream_id = stream_id; 336 308 urb->transfer_flags |= URB_FREE_BUFFER; 337 309 out: ··· 362 334 goto free; 363 335 364 336 iu->iu_id = IU_ID_COMMAND; 365 - iu->tag = cpu_to_be16(stream_id); 337 + if (blk_rq_tagged(cmnd->request)) 338 + iu->tag = cpu_to_be16(cmnd->request->tag + 2); 339 + else 340 + iu->tag = cpu_to_be16(1); 366 341 iu->prio_attr = UAS_SIMPLE_TAG; 367 342 iu->len = len; 368 343 int_to_scsilun(sdev->lun, &iu->lun); ··· 393 362 struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; 394 363 395 364 if (cmdinfo->state & ALLOC_STATUS_URB) { 396 - cmdinfo->status_urb = uas_alloc_sense_urb(devinfo, gfp, cmnd, 397 - cmdinfo->stream); 365 + cmdinfo->status_urb = uas_alloc_sense_urb(devinfo, gfp, 366 + cmnd->device->host, cmdinfo->stream); 398 367 if (!cmdinfo->status_urb) 399 368 return SCSI_MLQUEUE_DEVICE_BUSY; 400 369 cmdinfo->state &= ~ALLOC_STATUS_URB; ··· 475 444 476 445 BUILD_BUG_ON(sizeof(struct uas_cmd_info) > sizeof(struct scsi_pointer)); 477 446 478 - if (!cmdinfo->status_urb && sdev->current_cmnd) 447 + if (devinfo->cmnd) 479 448 return SCSI_MLQUEUE_DEVICE_BUSY; 480 449 481 450 if (blk_rq_tagged(cmnd->request)) { 482 - cmdinfo->stream = cmnd->request->tag + 1; 451 + cmdinfo->stream = cmnd->request->tag + 2; 483 452 } else { 484 - sdev->current_cmnd = cmnd; 453 + devinfo->cmnd = cmnd; 485 454 cmdinfo->stream = 1; 486 455 } 487 456 ··· 503 472 } 504 473 505 474 if (!devinfo->use_streams) { 506 - cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB); 475 + cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB | 476 + ALLOC_STATUS_URB | SUBMIT_STATUS_URB); 507 477 cmdinfo->stream = 0; 508 478 } 509 479 ··· 583 551 { 584 552 struct uas_dev_info *devinfo = sdev->hostdata; 585 553 scsi_set_tag_type(sdev, MSG_ORDERED_TAG); 586 - scsi_activate_tcq(sdev, devinfo->qdepth - 1); 554 + scsi_activate_tcq(sdev, devinfo->qdepth - 2); 587 555 return 0; 588 556 } 589 557 ··· 651 619 unsigned i, n_endpoints = intf->cur_altsetting->desc.bNumEndpoints; 652 620 653 621 devinfo->uas_sense_old = 0; 622 + devinfo->cmnd = NULL; 654 623 655 624 for (i = 0; i < n_endpoints; i++) { 656 625 unsigned char *extra = endpoint[i].extra; ··· 703 670 } 704 671 } 705 672 673 + static int uas_alloc_status_urb(struct uas_dev_info *devinfo, 674 + struct Scsi_Host *shost) 675 + { 676 + if (devinfo->use_streams) { 677 + devinfo->status_urb = NULL; 678 + return 0; 679 + } 680 + 681 + devinfo->status_urb = uas_alloc_sense_urb(devinfo, GFP_KERNEL, 682 + shost, 0); 683 + if (!devinfo->status_urb) 684 + goto err_s_urb; 685 + 686 + if (usb_submit_urb(devinfo->status_urb, GFP_KERNEL)) 687 + goto err_submit_urb; 688 + 689 + return 0; 690 + err_submit_urb: 691 + usb_free_urb(devinfo->status_urb); 692 + err_s_urb: 693 + return -ENOMEM; 694 + } 695 + 696 + static void uas_free_streams(struct uas_dev_info *devinfo) 697 + { 698 + struct usb_device *udev = devinfo->udev; 699 + struct usb_host_endpoint *eps[3]; 700 + 701 + eps[0] = usb_pipe_endpoint(udev, devinfo->status_pipe); 702 + eps[1] = usb_pipe_endpoint(udev, devinfo->data_in_pipe); 703 + eps[2] = usb_pipe_endpoint(udev, devinfo->data_out_pipe); 704 + usb_free_streams(devinfo->intf, eps, 3, GFP_KERNEL); 705 + } 706 + 706 707 /* 707 708 * XXX: What I'd like to do here is register a SCSI host for each USB host in 708 709 * the system. Follow usb-storage's design of registering a SCSI host for ··· 766 699 shost->max_id = 1; 767 700 shost->sg_tablesize = udev->bus->sg_tablesize; 768 701 769 - result = scsi_add_host(shost, &intf->dev); 770 - if (result) 771 - goto free; 772 - shost->hostdata[0] = (unsigned long)devinfo; 773 - 774 702 devinfo->intf = intf; 775 703 devinfo->udev = udev; 776 704 uas_configure_endpoints(devinfo); 777 705 706 + result = scsi_init_shared_tag_map(shost, devinfo->qdepth - 2); 707 + if (result) 708 + goto free; 709 + 710 + result = scsi_add_host(shost, &intf->dev); 711 + if (result) 712 + goto deconfig_eps; 713 + 714 + shost->hostdata[0] = (unsigned long)devinfo; 715 + 716 + result = uas_alloc_status_urb(devinfo, shost); 717 + if (result) 718 + goto err_alloc_status; 719 + 778 720 scsi_scan_host(shost); 779 721 usb_set_intfdata(intf, shost); 780 722 return result; 723 + 724 + err_alloc_status: 725 + scsi_remove_host(shost); 726 + shost = NULL; 727 + deconfig_eps: 728 + uas_free_streams(devinfo); 781 729 free: 782 730 kfree(devinfo); 783 731 if (shost) ··· 814 732 815 733 static void uas_disconnect(struct usb_interface *intf) 816 734 { 817 - struct usb_device *udev = interface_to_usbdev(intf); 818 - struct usb_host_endpoint *eps[3]; 819 735 struct Scsi_Host *shost = usb_get_intfdata(intf); 820 736 struct uas_dev_info *devinfo = (void *)shost->hostdata[0]; 821 737 822 738 scsi_remove_host(shost); 823 - 824 - eps[0] = usb_pipe_endpoint(udev, devinfo->status_pipe); 825 - eps[1] = usb_pipe_endpoint(udev, devinfo->data_in_pipe); 826 - eps[2] = usb_pipe_endpoint(udev, devinfo->data_out_pipe); 827 - usb_free_streams(intf, eps, 3, GFP_KERNEL); 828 - 739 + usb_kill_urb(devinfo->status_urb); 740 + usb_free_urb(devinfo->status_urb); 741 + uas_free_streams(devinfo); 829 742 kfree(devinfo); 830 743 } 831 744