From 24f531371de17010f2b1b57d90e42240032e7733 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 7 Aug 2013 10:58:05 -0400 Subject: USB: EHCI: accept very late isochronous URBs Since commits 4005ad4390bf (EHCI: implement new semantics for URB_ISO_ASAP) and c75c5ab575af (ALSA: USB: adjust for changed 3.8 USB API) became widely distributed, people have been experiencing problems with audio transfers. The slightest underrun causes complete failure, requiring the audio stream to be restarted. It turns out that the current isochronous API doesn't handle underruns in the best way. The ALSA developers would much rather have transfers that are submitted too late be accepted and complete in the normal fashion, rather than being refused outright. This patch implements the requested approach. When an isochronous URB submission is so late that all its scheduled slots have already expired, a debugging message will be printed in the log and the URB will be accepted as usual. Assuming it was submitted by a completion handler (which is normally the case), it will complete shortly thereafter with all the usb_iso_packet_descriptor status fields marked -EXDEV. This fixes (for ehci-hcd) https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1191603 It should be applied to all kernels that include commit 4005ad4390bf. Signed-off-by: Alan Stern Tested-by: Maksim Boyko CC: Clemens Ladisch CC: Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-sched.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index f80d0330d548..8e3c878f38cf 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -1391,21 +1391,20 @@ iso_stream_schedule ( /* Behind the scheduling threshold? */ if (unlikely(start < next)) { + unsigned now2 = (now - base) & (mod - 1); /* USB_ISO_ASAP: Round up to the first available slot */ if (urb->transfer_flags & URB_ISO_ASAP) start += (next - start + period - 1) & -period; /* - * Not ASAP: Use the next slot in the stream. If - * the entire URB falls before the threshold, fail. + * Not ASAP: Use the next slot in the stream, + * no matter what. */ - else if (start + span - period < next) { - ehci_dbg(ehci, "iso urb late %p (%u+%u < %u)\n", + else if (start + span - period < now2) { + ehci_dbg(ehci, "iso underrun %p (%u+%u < %u)\n", urb, start + base, - span - period, next + base); - status = -EXDEV; - goto fail; + span - period, now2 + base); } } -- cgit v1.2.3 From ec58fad1feb76c323ef47efff1d1e8660ed4644c Mon Sep 17 00:00:00 2001 From: Thomas Pugliese Date: Fri, 9 Aug 2013 09:52:13 -0500 Subject: wusbcore: fix kernel panic when disconnecting a wireless USB->serial device This patch fixes a kernel panic that can occur when disconnecting a wireless USB->serial device. When the serial device disconnects, the device cleanup procedure ends up calling usb_hcd_disable_endpoint on the serial device's endpoints. The wusbcore uses the ABORT_RPIPE command to abort all transfers on the given endpoint but it does not properly give back the URBs when the transfer results return from the HWA. This patch prevents the transfer result processing code from bailing out when it sees a WA_XFER_STATUS_ABORTED result code so that these urbs are flushed properly by usb_hcd_disable_endpoint. It also updates wa_urb_dequeue to handle the case where the endpoint has already been cleaned up when usb_kill_urb is called which is where the panic originally occurred. Signed-off-by: Thomas Pugliese Signed-off-by: Greg Kroah-Hartman --- drivers/usb/wusbcore/wa-xfer.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c index 16968c899493..d3493ca0525d 100644 --- a/drivers/usb/wusbcore/wa-xfer.c +++ b/drivers/usb/wusbcore/wa-xfer.c @@ -1226,6 +1226,12 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb) } spin_lock_irqsave(&xfer->lock, flags); rpipe = xfer->ep->hcpriv; + if (rpipe == NULL) { + pr_debug("%s: xfer id 0x%08X has no RPIPE. %s", + __func__, wa_xfer_id(xfer), + "Probably already aborted.\n" ); + goto out_unlock; + } /* Check the delayed list -> if there, release and complete */ spin_lock_irqsave(&wa->xfer_list_lock, flags2); if (!list_empty(&xfer->list_node) && xfer->seg == NULL) @@ -1644,8 +1650,7 @@ static void wa_xfer_result_cb(struct urb *urb) break; } usb_status = xfer_result->bTransferStatus & 0x3f; - if (usb_status == WA_XFER_STATUS_ABORTED - || usb_status == WA_XFER_STATUS_NOT_FOUND) + if (usb_status == WA_XFER_STATUS_NOT_FOUND) /* taken care of already */ break; xfer_id = xfer_result->dwTransferID; -- cgit v1.2.3 From 6c1ee66a0b2bdbd64c078fba684d640cf2fd38a9 Mon Sep 17 00:00:00 2001 From: Matt Burtch Date: Mon, 12 Aug 2013 10:11:39 -0700 Subject: USB-Serial: Fix error handling of usb_wwan This fixes an issue where the bulk-in urb used for incoming data transfer is not resubmitted if the packet recieved contains an error status. This results in the driver locking until the port is closed and re-opened. Tested on a custom board with a Cinterion GSM module. Signed-off-by: Matt Burtch Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb_wwan.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index 8257d30c4072..85365784040b 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -291,18 +291,18 @@ static void usb_wwan_indat_callback(struct urb *urb) tty_flip_buffer_push(&port->port); } else dev_dbg(dev, "%s: empty read urb received\n", __func__); - - /* Resubmit urb so we continue receiving */ - err = usb_submit_urb(urb, GFP_ATOMIC); - if (err) { - if (err != -EPERM) { - dev_err(dev, "%s: resubmit read urb failed. (%d)\n", __func__, err); - /* busy also in error unless we are killed */ - usb_mark_last_busy(port->serial->dev); - } - } else { + } + /* Resubmit urb so we continue receiving */ + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err) { + if (err != -EPERM) { + dev_err(dev, "%s: resubmit read urb failed. (%d)\n", + __func__, err); + /* busy also in error unless we are killed */ usb_mark_last_busy(port->serial->dev); } + } else { + usb_mark_last_busy(port->serial->dev); } } -- cgit v1.2.3 From d551ec9b690f3de65b0091a2e767f1382adc792d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Sun, 11 Aug 2013 16:49:20 +0200 Subject: USB: mos7840: fix big-endian probe Fix bug in device-type detection on big-endian machines originally introduced by commit 0eafe4de ("USB: serial: mos7840: add support for MCS7810 devices") which always matched on little-endian product ids. Reported-by: kbuild test robot Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index d953d674f222..3bac4693c038 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -2193,7 +2193,7 @@ static int mos7810_check(struct usb_serial *serial) static int mos7840_probe(struct usb_serial *serial, const struct usb_device_id *id) { - u16 product = serial->dev->descriptor.idProduct; + u16 product = le16_to_cpu(serial->dev->descriptor.idProduct); u8 *buf; int device_type; -- cgit v1.2.3 From c786138fcc28d42754695ecdcbaba3d1c057f153 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Sun, 11 Aug 2013 16:49:21 +0200 Subject: USB: usbtmc: fix big-endian probe of Rigol devices Fix probe of Rigol devices on big-endian machines. A quirk for these devices was introduced by commit c2e314835 ("USB: usbtmc: Set rigol_quirk if device is listed") but was only enabled on little-endian machines. Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usbtmc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 609dbc2f7151..83b4ef4dfcf8 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -1119,11 +1119,11 @@ static int usbtmc_probe(struct usb_interface *intf, /* Determine if it is a Rigol or not */ data->rigol_quirk = 0; dev_dbg(&intf->dev, "Trying to find if device Vendor 0x%04X Product 0x%04X has the RIGOL quirk\n", - data->usb_dev->descriptor.idVendor, - data->usb_dev->descriptor.idProduct); + le16_to_cpu(data->usb_dev->descriptor.idVendor), + le16_to_cpu(data->usb_dev->descriptor.idProduct)); for(n = 0; usbtmc_id_quirk[n].idVendor > 0; n++) { - if ((usbtmc_id_quirk[n].idVendor == data->usb_dev->descriptor.idVendor) && - (usbtmc_id_quirk[n].idProduct == data->usb_dev->descriptor.idProduct)) { + if ((usbtmc_id_quirk[n].idVendor == le16_to_cpu(data->usb_dev->descriptor.idVendor)) && + (usbtmc_id_quirk[n].idProduct == le16_to_cpu(data->usb_dev->descriptor.idProduct))) { dev_dbg(&intf->dev, "Setting this device as having the RIGOL quirk\n"); data->rigol_quirk = 1; break; -- cgit v1.2.3 From d482b9d558602a9cacab063b1c8779f9b5214da7 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Sun, 11 Aug 2013 16:49:22 +0200 Subject: USB: adutux: fix big-endian device-type reporting Make sure the reported device-type on big-endian machines is the same as on little-endian ones. Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/adutux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index eb3c8c142fa9..eeb27208c0d1 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c @@ -830,7 +830,7 @@ static int adu_probe(struct usb_interface *interface, /* let the user know what node this device is now attached to */ dev_info(&interface->dev, "ADU%d %s now attached to /dev/usb/adutux%d\n", - udev->descriptor.idProduct, dev->serial_number, + le16_to_cpu(udev->descriptor.idProduct), dev->serial_number, (dev->minor - ADU_MINOR_BASE)); exit: dbg(2, " %s : leave, return value %p (dev)", __func__, dev); -- cgit v1.2.3 From e877dd2f2581628b7119df707d4cf03d940cff49 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Sun, 11 Aug 2013 16:49:23 +0200 Subject: USB: ti_usb_3410_5052: fix big-endian firmware handling Fix endianess bugs in firmware handling introduced by commits cb7a7c6a ("ti_usb_3410_5052: add Multi-Tech modem support") and 05a3d905 ("ti_usb_3410_5052: support alternate firmware") which made the driver use the wrong firmware for certain devices on big-endian machines. Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ti_usb_3410_5052.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 375b5a400b6f..5c9f9b1d7736 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -1536,14 +1536,15 @@ static int ti_download_firmware(struct ti_device *tdev) char buf[32]; /* try ID specific firmware first, then try generic firmware */ - sprintf(buf, "ti_usb-v%04x-p%04x.fw", dev->descriptor.idVendor, - dev->descriptor.idProduct); + sprintf(buf, "ti_usb-v%04x-p%04x.fw", + le16_to_cpu(dev->descriptor.idVendor), + le16_to_cpu(dev->descriptor.idProduct)); status = request_firmware(&fw_p, buf, &dev->dev); if (status != 0) { buf[0] = '\0'; - if (dev->descriptor.idVendor == MTS_VENDOR_ID) { - switch (dev->descriptor.idProduct) { + if (le16_to_cpu(dev->descriptor.idVendor) == MTS_VENDOR_ID) { + switch (le16_to_cpu(dev->descriptor.idProduct)) { case MTS_CDMA_PRODUCT_ID: strcpy(buf, "mts_cdma.fw"); break; -- cgit v1.2.3 From 304ab4ab079a8ed03ce39f1d274964a532db036b Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Wed, 14 Aug 2013 11:01:46 +0200 Subject: usb: add two quirky touchscreen These devices tend to become unresponsive after S3 Signed-off-by: Oliver Neukum CC: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/quirks.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index a63598895077..5b44cd47da5b 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -78,6 +78,12 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x04d8, 0x000c), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, + /* CarrolTouch 4000U */ + { USB_DEVICE(0x04e7, 0x0009), .driver_info = USB_QUIRK_RESET_RESUME }, + + /* CarrolTouch 4500U */ + { USB_DEVICE(0x04e7, 0x0030), .driver_info = USB_QUIRK_RESET_RESUME }, + /* Samsung Android phone modem - ID conflict with SPH-I500 */ { USB_DEVICE(0x04e8, 0x6601), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, -- cgit v1.2.3 From ef6c8c1d733e244f0499035be0dabe1f4ed98c6f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 13 Aug 2013 13:27:34 +0200 Subject: USB: mos7720: fix broken control requests The parallel-port code of the drivers used a stack allocated control-request buffer for asynchronous (and possibly deferred) control requests. This not only violates the no-DMA-from-stack requirement but could also lead to corrupt control requests being submitted. Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7720.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 51da424327b0..b01300164fc0 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -90,6 +90,7 @@ struct urbtracker { struct list_head urblist_entry; struct kref ref_count; struct urb *urb; + struct usb_ctrlrequest *setup; }; enum mos7715_pp_modes { @@ -271,6 +272,7 @@ static void destroy_urbtracker(struct kref *kref) struct mos7715_parport *mos_parport = urbtrack->mos_parport; usb_free_urb(urbtrack->urb); + kfree(urbtrack->setup); kfree(urbtrack); kref_put(&mos_parport->ref_count, destroy_mos_parport); } @@ -355,7 +357,6 @@ static int write_parport_reg_nonblock(struct mos7715_parport *mos_parport, struct urbtracker *urbtrack; int ret_val; unsigned long flags; - struct usb_ctrlrequest setup; struct usb_serial *serial = mos_parport->serial; struct usb_device *usbdev = serial->dev; @@ -373,14 +374,20 @@ static int write_parport_reg_nonblock(struct mos7715_parport *mos_parport, kfree(urbtrack); return -ENOMEM; } - setup.bRequestType = (__u8)0x40; - setup.bRequest = (__u8)0x0e; - setup.wValue = get_reg_value(reg, dummy); - setup.wIndex = get_reg_index(reg); - setup.wLength = 0; + urbtrack->setup = kmalloc(sizeof(*urbtrack->setup), GFP_KERNEL); + if (!urbtrack->setup) { + usb_free_urb(urbtrack->urb); + kfree(urbtrack); + return -ENOMEM; + } + urbtrack->setup->bRequestType = (__u8)0x40; + urbtrack->setup->bRequest = (__u8)0x0e; + urbtrack->setup->wValue = get_reg_value(reg, dummy); + urbtrack->setup->wIndex = get_reg_index(reg); + urbtrack->setup->wLength = 0; usb_fill_control_urb(urbtrack->urb, usbdev, usb_sndctrlpipe(usbdev, 0), - (unsigned char *)&setup, + (unsigned char *)urbtrack->setup, NULL, 0, async_complete, urbtrack); kref_init(&urbtrack->ref_count); INIT_LIST_HEAD(&urbtrack->urblist_entry); -- cgit v1.2.3 From ff8a43c10f1440f07a5faca0c1556921259f7f76 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 13 Aug 2013 13:27:35 +0200 Subject: USB: keyspan: fix null-deref at disconnect and release Make sure to fail properly if the device is not accepted during attach in order to avoid null-pointer derefs (of missing interface private data) at disconnect or release. Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/keyspan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 5a979729f8ec..58c17fdc85eb 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -2303,7 +2303,7 @@ static int keyspan_startup(struct usb_serial *serial) if (d_details == NULL) { dev_err(&serial->dev->dev, "%s - unknown product id %x\n", __func__, le16_to_cpu(serial->dev->descriptor.idProduct)); - return 1; + return -ENODEV; } /* Setup private data for serial driver */ -- cgit v1.2.3