USB fixes for 3.11-rc6
Here are some small USB fixes for 3.11-rc6 that have accumulated. Nothing huge, a EHCI fix that solves a much-reported audio USB problem, some usb-serial driver endian fixes and other minor fixes, a wireless USB oops fix, and two new quirks. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.20 (GNU/Linux) iEYEABECAAYFAlINiREACgkQMUfUDdst+ynMkACgvH7Xfb6U27cAsf+Pf03lhWyg 4+sAnjKq3kD+UXwIaaSIeod5xEKLZLLk =+24N -----END PGP SIGNATURE----- Merge tag 'usb-3.11-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb Pull USB fixes from Greg KH: "Here are some small USB fixes for 3.11-rc6 that have accumulated. Nothing huge, a EHCI fix that solves a much-reported audio USB problem, some usb-serial driver endian fixes and other minor fixes, a wireless USB oops fix, and two new quirks" * tag 'usb-3.11-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: USB: keyspan: fix null-deref at disconnect and release USB: mos7720: fix broken control requests usb: add two quirky touchscreen USB: ti_usb_3410_5052: fix big-endian firmware handling USB: adutux: fix big-endian device-type reporting USB: usbtmc: fix big-endian probe of Rigol devices USB: mos7840: fix big-endian probe USB-Serial: Fix error handling of usb_wwan wusbcore: fix kernel panic when disconnecting a wireless USB->serial device USB: EHCI: accept very late isochronous URBs
This commit is contained in:
commit
89cb9ae238
|
@ -1119,11 +1119,11 @@ static int usbtmc_probe(struct usb_interface *intf,
|
||||||
/* Determine if it is a Rigol or not */
|
/* Determine if it is a Rigol or not */
|
||||||
data->rigol_quirk = 0;
|
data->rigol_quirk = 0;
|
||||||
dev_dbg(&intf->dev, "Trying to find if device Vendor 0x%04X Product 0x%04X has the RIGOL quirk\n",
|
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,
|
le16_to_cpu(data->usb_dev->descriptor.idVendor),
|
||||||
data->usb_dev->descriptor.idProduct);
|
le16_to_cpu(data->usb_dev->descriptor.idProduct));
|
||||||
for(n = 0; usbtmc_id_quirk[n].idVendor > 0; n++) {
|
for(n = 0; usbtmc_id_quirk[n].idVendor > 0; n++) {
|
||||||
if ((usbtmc_id_quirk[n].idVendor == data->usb_dev->descriptor.idVendor) &&
|
if ((usbtmc_id_quirk[n].idVendor == le16_to_cpu(data->usb_dev->descriptor.idVendor)) &&
|
||||||
(usbtmc_id_quirk[n].idProduct == data->usb_dev->descriptor.idProduct)) {
|
(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");
|
dev_dbg(&intf->dev, "Setting this device as having the RIGOL quirk\n");
|
||||||
data->rigol_quirk = 1;
|
data->rigol_quirk = 1;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -78,6 +78,12 @@ static const struct usb_device_id usb_quirk_list[] = {
|
||||||
{ USB_DEVICE(0x04d8, 0x000c), .driver_info =
|
{ USB_DEVICE(0x04d8, 0x000c), .driver_info =
|
||||||
USB_QUIRK_CONFIG_INTF_STRINGS },
|
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 */
|
/* Samsung Android phone modem - ID conflict with SPH-I500 */
|
||||||
{ USB_DEVICE(0x04e8, 0x6601), .driver_info =
|
{ USB_DEVICE(0x04e8, 0x6601), .driver_info =
|
||||||
USB_QUIRK_CONFIG_INTF_STRINGS },
|
USB_QUIRK_CONFIG_INTF_STRINGS },
|
||||||
|
|
|
@ -1391,21 +1391,20 @@ iso_stream_schedule (
|
||||||
|
|
||||||
/* Behind the scheduling threshold? */
|
/* Behind the scheduling threshold? */
|
||||||
if (unlikely(start < next)) {
|
if (unlikely(start < next)) {
|
||||||
|
unsigned now2 = (now - base) & (mod - 1);
|
||||||
|
|
||||||
/* USB_ISO_ASAP: Round up to the first available slot */
|
/* USB_ISO_ASAP: Round up to the first available slot */
|
||||||
if (urb->transfer_flags & URB_ISO_ASAP)
|
if (urb->transfer_flags & URB_ISO_ASAP)
|
||||||
start += (next - start + period - 1) & -period;
|
start += (next - start + period - 1) & -period;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Not ASAP: Use the next slot in the stream. If
|
* Not ASAP: Use the next slot in the stream,
|
||||||
* the entire URB falls before the threshold, fail.
|
* no matter what.
|
||||||
*/
|
*/
|
||||||
else if (start + span - period < next) {
|
else if (start + span - period < now2) {
|
||||||
ehci_dbg(ehci, "iso urb late %p (%u+%u < %u)\n",
|
ehci_dbg(ehci, "iso underrun %p (%u+%u < %u)\n",
|
||||||
urb, start + base,
|
urb, start + base,
|
||||||
span - period, next + base);
|
span - period, now2 + base);
|
||||||
status = -EXDEV;
|
|
||||||
goto fail;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -830,7 +830,7 @@ static int adu_probe(struct usb_interface *interface,
|
||||||
|
|
||||||
/* let the user know what node this device is now attached to */
|
/* 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",
|
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));
|
(dev->minor - ADU_MINOR_BASE));
|
||||||
exit:
|
exit:
|
||||||
dbg(2, " %s : leave, return value %p (dev)", __func__, dev);
|
dbg(2, " %s : leave, return value %p (dev)", __func__, dev);
|
||||||
|
|
|
@ -2303,7 +2303,7 @@ static int keyspan_startup(struct usb_serial *serial)
|
||||||
if (d_details == NULL) {
|
if (d_details == NULL) {
|
||||||
dev_err(&serial->dev->dev, "%s - unknown product id %x\n",
|
dev_err(&serial->dev->dev, "%s - unknown product id %x\n",
|
||||||
__func__, le16_to_cpu(serial->dev->descriptor.idProduct));
|
__func__, le16_to_cpu(serial->dev->descriptor.idProduct));
|
||||||
return 1;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Setup private data for serial driver */
|
/* Setup private data for serial driver */
|
||||||
|
|
|
@ -90,6 +90,7 @@ struct urbtracker {
|
||||||
struct list_head urblist_entry;
|
struct list_head urblist_entry;
|
||||||
struct kref ref_count;
|
struct kref ref_count;
|
||||||
struct urb *urb;
|
struct urb *urb;
|
||||||
|
struct usb_ctrlrequest *setup;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum mos7715_pp_modes {
|
enum mos7715_pp_modes {
|
||||||
|
@ -271,6 +272,7 @@ static void destroy_urbtracker(struct kref *kref)
|
||||||
struct mos7715_parport *mos_parport = urbtrack->mos_parport;
|
struct mos7715_parport *mos_parport = urbtrack->mos_parport;
|
||||||
|
|
||||||
usb_free_urb(urbtrack->urb);
|
usb_free_urb(urbtrack->urb);
|
||||||
|
kfree(urbtrack->setup);
|
||||||
kfree(urbtrack);
|
kfree(urbtrack);
|
||||||
kref_put(&mos_parport->ref_count, destroy_mos_parport);
|
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;
|
struct urbtracker *urbtrack;
|
||||||
int ret_val;
|
int ret_val;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct usb_ctrlrequest setup;
|
|
||||||
struct usb_serial *serial = mos_parport->serial;
|
struct usb_serial *serial = mos_parport->serial;
|
||||||
struct usb_device *usbdev = serial->dev;
|
struct usb_device *usbdev = serial->dev;
|
||||||
|
|
||||||
|
@ -373,14 +374,20 @@ static int write_parport_reg_nonblock(struct mos7715_parport *mos_parport,
|
||||||
kfree(urbtrack);
|
kfree(urbtrack);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
setup.bRequestType = (__u8)0x40;
|
urbtrack->setup = kmalloc(sizeof(*urbtrack->setup), GFP_KERNEL);
|
||||||
setup.bRequest = (__u8)0x0e;
|
if (!urbtrack->setup) {
|
||||||
setup.wValue = get_reg_value(reg, dummy);
|
usb_free_urb(urbtrack->urb);
|
||||||
setup.wIndex = get_reg_index(reg);
|
kfree(urbtrack);
|
||||||
setup.wLength = 0;
|
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_fill_control_urb(urbtrack->urb, usbdev,
|
||||||
usb_sndctrlpipe(usbdev, 0),
|
usb_sndctrlpipe(usbdev, 0),
|
||||||
(unsigned char *)&setup,
|
(unsigned char *)urbtrack->setup,
|
||||||
NULL, 0, async_complete, urbtrack);
|
NULL, 0, async_complete, urbtrack);
|
||||||
kref_init(&urbtrack->ref_count);
|
kref_init(&urbtrack->ref_count);
|
||||||
INIT_LIST_HEAD(&urbtrack->urblist_entry);
|
INIT_LIST_HEAD(&urbtrack->urblist_entry);
|
||||||
|
|
|
@ -2193,7 +2193,7 @@ static int mos7810_check(struct usb_serial *serial)
|
||||||
static int mos7840_probe(struct usb_serial *serial,
|
static int mos7840_probe(struct usb_serial *serial,
|
||||||
const struct usb_device_id *id)
|
const struct usb_device_id *id)
|
||||||
{
|
{
|
||||||
u16 product = serial->dev->descriptor.idProduct;
|
u16 product = le16_to_cpu(serial->dev->descriptor.idProduct);
|
||||||
u8 *buf;
|
u8 *buf;
|
||||||
int device_type;
|
int device_type;
|
||||||
|
|
||||||
|
|
|
@ -1536,14 +1536,15 @@ static int ti_download_firmware(struct ti_device *tdev)
|
||||||
char buf[32];
|
char buf[32];
|
||||||
|
|
||||||
/* try ID specific firmware first, then try generic firmware */
|
/* try ID specific firmware first, then try generic firmware */
|
||||||
sprintf(buf, "ti_usb-v%04x-p%04x.fw", dev->descriptor.idVendor,
|
sprintf(buf, "ti_usb-v%04x-p%04x.fw",
|
||||||
dev->descriptor.idProduct);
|
le16_to_cpu(dev->descriptor.idVendor),
|
||||||
|
le16_to_cpu(dev->descriptor.idProduct));
|
||||||
status = request_firmware(&fw_p, buf, &dev->dev);
|
status = request_firmware(&fw_p, buf, &dev->dev);
|
||||||
|
|
||||||
if (status != 0) {
|
if (status != 0) {
|
||||||
buf[0] = '\0';
|
buf[0] = '\0';
|
||||||
if (dev->descriptor.idVendor == MTS_VENDOR_ID) {
|
if (le16_to_cpu(dev->descriptor.idVendor) == MTS_VENDOR_ID) {
|
||||||
switch (dev->descriptor.idProduct) {
|
switch (le16_to_cpu(dev->descriptor.idProduct)) {
|
||||||
case MTS_CDMA_PRODUCT_ID:
|
case MTS_CDMA_PRODUCT_ID:
|
||||||
strcpy(buf, "mts_cdma.fw");
|
strcpy(buf, "mts_cdma.fw");
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -291,18 +291,18 @@ static void usb_wwan_indat_callback(struct urb *urb)
|
||||||
tty_flip_buffer_push(&port->port);
|
tty_flip_buffer_push(&port->port);
|
||||||
} else
|
} else
|
||||||
dev_dbg(dev, "%s: empty read urb received\n", __func__);
|
dev_dbg(dev, "%s: empty read urb received\n", __func__);
|
||||||
|
}
|
||||||
/* Resubmit urb so we continue receiving */
|
/* Resubmit urb so we continue receiving */
|
||||||
err = usb_submit_urb(urb, GFP_ATOMIC);
|
err = usb_submit_urb(urb, GFP_ATOMIC);
|
||||||
if (err) {
|
if (err) {
|
||||||
if (err != -EPERM) {
|
if (err != -EPERM) {
|
||||||
dev_err(dev, "%s: resubmit read urb failed. (%d)\n", __func__, err);
|
dev_err(dev, "%s: resubmit read urb failed. (%d)\n",
|
||||||
/* busy also in error unless we are killed */
|
__func__, err);
|
||||||
usb_mark_last_busy(port->serial->dev);
|
/* busy also in error unless we are killed */
|
||||||
}
|
|
||||||
} else {
|
|
||||||
usb_mark_last_busy(port->serial->dev);
|
usb_mark_last_busy(port->serial->dev);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
usb_mark_last_busy(port->serial->dev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1226,6 +1226,12 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb)
|
||||||
}
|
}
|
||||||
spin_lock_irqsave(&xfer->lock, flags);
|
spin_lock_irqsave(&xfer->lock, flags);
|
||||||
rpipe = xfer->ep->hcpriv;
|
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 */
|
/* Check the delayed list -> if there, release and complete */
|
||||||
spin_lock_irqsave(&wa->xfer_list_lock, flags2);
|
spin_lock_irqsave(&wa->xfer_list_lock, flags2);
|
||||||
if (!list_empty(&xfer->list_node) && xfer->seg == NULL)
|
if (!list_empty(&xfer->list_node) && xfer->seg == NULL)
|
||||||
|
@ -1644,8 +1650,7 @@ static void wa_xfer_result_cb(struct urb *urb)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
usb_status = xfer_result->bTransferStatus & 0x3f;
|
usb_status = xfer_result->bTransferStatus & 0x3f;
|
||||||
if (usb_status == WA_XFER_STATUS_ABORTED
|
if (usb_status == WA_XFER_STATUS_NOT_FOUND)
|
||||||
|| usb_status == WA_XFER_STATUS_NOT_FOUND)
|
|
||||||
/* taken care of already */
|
/* taken care of already */
|
||||||
break;
|
break;
|
||||||
xfer_id = xfer_result->dwTransferID;
|
xfer_id = xfer_result->dwTransferID;
|
||||||
|
|
Loading…
Reference in a new issue