|
@@ -131,7 +131,8 @@ static const struct usb_device_id btusb_table[] = {
|
|
|
{ USB_DEVICE(0x19ff, 0x0239), .driver_info = BTUSB_BCM_PATCHRAM },
|
|
|
|
|
|
/* Broadcom BCM43142A0 (Foxconn/Lenovo) */
|
|
|
- { USB_DEVICE(0x105b, 0xe065), .driver_info = BTUSB_BCM_PATCHRAM },
|
|
|
+ { USB_VENDOR_AND_INTERFACE_INFO(0x105b, 0xff, 0x01, 0x01),
|
|
|
+ .driver_info = BTUSB_BCM_PATCHRAM },
|
|
|
|
|
|
/* Broadcom BCM920703 (HTC Vive) */
|
|
|
{ USB_VENDOR_AND_INTERFACE_INFO(0x0bb4, 0xff, 0x01, 0x01),
|
|
@@ -268,6 +269,7 @@ static const struct usb_device_id blacklist_table[] = {
|
|
|
{ USB_DEVICE(0x0489, 0xe092), .driver_info = BTUSB_QCA_ROME },
|
|
|
{ USB_DEVICE(0x0489, 0xe0a2), .driver_info = BTUSB_QCA_ROME },
|
|
|
{ USB_DEVICE(0x04ca, 0x3011), .driver_info = BTUSB_QCA_ROME },
|
|
|
+ { USB_DEVICE(0x04ca, 0x3016), .driver_info = BTUSB_QCA_ROME },
|
|
|
|
|
|
/* Broadcom BCM2035 */
|
|
|
{ USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 },
|
|
@@ -656,7 +658,8 @@ static void btusb_intr_complete(struct urb *urb)
|
|
|
err = usb_submit_urb(urb, GFP_ATOMIC);
|
|
|
if (err < 0) {
|
|
|
/* -EPERM: urb is being killed;
|
|
|
- * -ENODEV: device got disconnected */
|
|
|
+ * -ENODEV: device got disconnected
|
|
|
+ */
|
|
|
if (err != -EPERM && err != -ENODEV)
|
|
|
BT_ERR("%s urb %p failed to resubmit (%d)",
|
|
|
hdev->name, urb, -err);
|
|
@@ -745,7 +748,8 @@ static void btusb_bulk_complete(struct urb *urb)
|
|
|
err = usb_submit_urb(urb, GFP_ATOMIC);
|
|
|
if (err < 0) {
|
|
|
/* -EPERM: urb is being killed;
|
|
|
- * -ENODEV: device got disconnected */
|
|
|
+ * -ENODEV: device got disconnected
|
|
|
+ */
|
|
|
if (err != -EPERM && err != -ENODEV)
|
|
|
BT_ERR("%s urb %p failed to resubmit (%d)",
|
|
|
hdev->name, urb, -err);
|
|
@@ -840,7 +844,8 @@ static void btusb_isoc_complete(struct urb *urb)
|
|
|
err = usb_submit_urb(urb, GFP_ATOMIC);
|
|
|
if (err < 0) {
|
|
|
/* -EPERM: urb is being killed;
|
|
|
- * -ENODEV: device got disconnected */
|
|
|
+ * -ENODEV: device got disconnected
|
|
|
+ */
|
|
|
if (err != -EPERM && err != -ENODEV)
|
|
|
BT_ERR("%s urb %p failed to resubmit (%d)",
|
|
|
hdev->name, urb, -err);
|
|
@@ -952,7 +957,8 @@ static void btusb_diag_complete(struct urb *urb)
|
|
|
err = usb_submit_urb(urb, GFP_ATOMIC);
|
|
|
if (err < 0) {
|
|
|
/* -EPERM: urb is being killed;
|
|
|
- * -ENODEV: device got disconnected */
|
|
|
+ * -ENODEV: device got disconnected
|
|
|
+ */
|
|
|
if (err != -EPERM && err != -ENODEV)
|
|
|
BT_ERR("%s urb %p failed to resubmit (%d)",
|
|
|
hdev->name, urb, -err);
|
|
@@ -2896,7 +2902,8 @@ static int btusb_probe(struct usb_interface *intf,
|
|
|
struct usb_device *udev = interface_to_usbdev(intf);
|
|
|
|
|
|
/* Old firmware would otherwise let ath3k driver load
|
|
|
- * patch and sysconfig files */
|
|
|
+ * patch and sysconfig files
|
|
|
+ */
|
|
|
if (le16_to_cpu(udev->descriptor.bcdDevice) <= 0x0001)
|
|
|
return -ENODEV;
|
|
|
}
|
|
@@ -3067,6 +3074,12 @@ static int btusb_probe(struct usb_interface *intf,
|
|
|
if (id->driver_info & BTUSB_QCA_ROME) {
|
|
|
data->setup_on_usb = btusb_setup_qca;
|
|
|
hdev->set_bdaddr = btusb_set_bdaddr_ath3012;
|
|
|
+
|
|
|
+ /* QCA Rome devices lose their updated firmware over suspend,
|
|
|
+ * but the USB hub doesn't notice any status change.
|
|
|
+ * Explicitly request a device reset on resume.
|
|
|
+ */
|
|
|
+ set_bit(BTUSB_RESET_RESUME, &data->flags);
|
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_BT_HCIBTUSB_RTL
|
|
@@ -3259,13 +3272,28 @@ static void play_deferred(struct btusb_data *data)
|
|
|
int err;
|
|
|
|
|
|
while ((urb = usb_get_from_anchor(&data->deferred))) {
|
|
|
+ usb_anchor_urb(urb, &data->tx_anchor);
|
|
|
+
|
|
|
err = usb_submit_urb(urb, GFP_ATOMIC);
|
|
|
- if (err < 0)
|
|
|
+ if (err < 0) {
|
|
|
+ if (err != -EPERM && err != -ENODEV)
|
|
|
+ BT_ERR("%s urb %p submission failed (%d)",
|
|
|
+ data->hdev->name, urb, -err);
|
|
|
+ kfree(urb->setup_packet);
|
|
|
+ usb_unanchor_urb(urb);
|
|
|
+ usb_free_urb(urb);
|
|
|
break;
|
|
|
+ }
|
|
|
|
|
|
data->tx_in_flight++;
|
|
|
+ usb_free_urb(urb);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Cleanup the rest deferred urbs. */
|
|
|
+ while ((urb = usb_get_from_anchor(&data->deferred))) {
|
|
|
+ kfree(urb->setup_packet);
|
|
|
+ usb_free_urb(urb);
|
|
|
}
|
|
|
- usb_scuttle_anchored_urbs(&data->deferred);
|
|
|
}
|
|
|
|
|
|
static int btusb_resume(struct usb_interface *intf)
|