When a USB device is disconnected (or a driver is unbound from a device), the USB core will automatically cancel any URBs, and possibly clean up any host controller state associated with the device. This may include setting the alternate interface setting back to alt setting 0. Unfortunately, the xHCI needs any bulk stream rings to be freed before the next alt setting is installed, and the USB core has no idea which endpoints has stream rings allocated. Instead, the UAS driver needs to set the soft_unbind flag, which tells the USB core that it will cancel any pending URBs and clean up any extra state (including the stream rings). Make the UAS disconnect method go through the same process as the pre_reset method to quiesce all command submission, wait for all URBs to be killed, and free the stream rings. Signed-off-by: Sarah Sharp <sarah.a.sharp@xxxxxxxxxxxxxxx> Cc: Matthew Wilcox <willy@xxxxxxxxxxxxxxx> --- drivers/usb/storage/uas.c | 11 ++++------- 1 files changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index e3c5426..600edbc 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -1078,18 +1078,13 @@ static int uas_post_reset(struct usb_interface *intf) static void uas_disconnect(struct usb_interface *intf) { - struct usb_device *udev = interface_to_usbdev(intf); - struct usb_host_endpoint *eps[3]; struct Scsi_Host *shost = usb_get_intfdata(intf); struct uas_dev_info *devinfo = (void *)shost->hostdata[0]; + /* Clean up any pending commands and free streams */ + uas_pre_reset(intf); scsi_remove_host(shost); - eps[0] = usb_pipe_endpoint(udev, devinfo->status_pipe); - eps[1] = usb_pipe_endpoint(udev, devinfo->data_in_pipe); - eps[2] = usb_pipe_endpoint(udev, devinfo->data_out_pipe); - usb_free_streams(intf, eps, 3, GFP_KERNEL); - cleanup_srcu_struct(devinfo->srcu); kfree(devinfo->srcu); kfree(devinfo->anchors); @@ -1107,6 +1102,8 @@ static struct usb_driver uas_driver = { .pre_reset = uas_pre_reset, .post_reset = uas_post_reset, .id_table = uas_usb_ids, + /* UAS needs to free URBs and streams before USB core disables eps */ + .soft_unbind = 1, }; static int uas_init(void) -- 1.7.5.4 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html