These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / bluetooth / btusb.c
index c655015..9688971 100644 (file)
 
 #include "btintel.h"
 #include "btbcm.h"
+#include "btrtl.h"
 
 #define VERSION "0.8"
 
 static bool disable_scofix;
 static bool force_scofix;
 
-static bool reset = 1;
+static bool reset = true;
 
 static struct usb_driver btusb_driver;
 
@@ -59,6 +60,8 @@ static struct usb_driver btusb_driver;
 #define BTUSB_QCA_ROME         0x8000
 #define BTUSB_BCM_APPLE                0x10000
 #define BTUSB_REALTEK          0x20000
+#define BTUSB_BCM2045          0x40000
+#define BTUSB_IFNUM_2          0x80000
 
 static const struct usb_device_id btusb_table[] = {
        /* Generic Bluetooth USB device */
@@ -67,9 +70,12 @@ static const struct usb_device_id btusb_table[] = {
        /* Generic Bluetooth AMP device */
        { USB_DEVICE_INFO(0xe0, 0x01, 0x04), .driver_info = BTUSB_AMP },
 
+       /* Generic Bluetooth USB interface */
+       { USB_INTERFACE_INFO(0xe0, 0x01, 0x01) },
+
        /* Apple-specific (Broadcom) devices */
        { USB_VENDOR_AND_INTERFACE_INFO(0x05ac, 0xff, 0x01, 0x01),
-         .driver_info = BTUSB_BCM_APPLE },
+         .driver_info = BTUSB_BCM_APPLE | BTUSB_IFNUM_2 },
 
        /* MediaTek MT76x0E */
        { USB_DEVICE(0x0e8d, 0x763f) },
@@ -120,6 +126,9 @@ static const struct usb_device_id btusb_table[] = {
        /* Broadcom BCM20702B0 (Dynex/Insignia) */
        { USB_DEVICE(0x19ff, 0x0239), .driver_info = BTUSB_BCM_PATCHRAM },
 
+       /* Broadcom BCM43142A0 (Foxconn/Lenovo) */
+       { USB_DEVICE(0x105b, 0xe065), .driver_info = BTUSB_BCM_PATCHRAM },
+
        /* Foxconn - Hon Hai */
        { USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01),
          .driver_info = BTUSB_BCM_PATCHRAM },
@@ -144,6 +153,10 @@ static const struct usb_device_id btusb_table[] = {
        { USB_VENDOR_AND_INTERFACE_INFO(0x13d3, 0xff, 0x01, 0x01),
          .driver_info = BTUSB_BCM_PATCHRAM },
 
+       /* Toshiba Corp - Broadcom based */
+       { USB_VENDOR_AND_INTERFACE_INFO(0x0930, 0xff, 0x01, 0x01),
+         .driver_info = BTUSB_BCM_PATCHRAM },
+
        /* Intel Bluetooth USB Bootloader (RAM module) */
        { USB_DEVICE(0x8087, 0x0a5a),
          .driver_info = BTUSB_INTEL_BOOT | BTUSB_BROKEN_ISOC },
@@ -160,6 +173,9 @@ static const struct usb_device_id blacklist_table[] = {
        /* Broadcom BCM2033 without firmware */
        { USB_DEVICE(0x0a5c, 0x2033), .driver_info = BTUSB_IGNORE },
 
+       /* Broadcom BCM2045 devices */
+       { USB_DEVICE(0x0a5c, 0x2045), .driver_info = BTUSB_BCM2045 },
+
        /* Atheros 3011 with sflash firmware */
        { USB_DEVICE(0x0489, 0xe027), .driver_info = BTUSB_IGNORE },
        { USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE },
@@ -191,6 +207,7 @@ static const struct usb_device_id blacklist_table[] = {
        { USB_DEVICE(0x04ca, 0x300f), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0930, 0x021c), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0930, 0x0227), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 },
@@ -202,6 +219,7 @@ static const struct usb_device_id blacklist_table[] = {
        { USB_DEVICE(0x0cf3, 0x311f), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0x817b), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
@@ -318,6 +336,9 @@ static const struct usb_device_id blacklist_table[] = {
        { USB_DEVICE(0x13d3, 0x3461), .driver_info = BTUSB_REALTEK },
        { USB_DEVICE(0x13d3, 0x3462), .driver_info = BTUSB_REALTEK },
 
+       /* Silicon Wave based devices */
+       { USB_DEVICE(0x0c10, 0x0000), .driver_info = BTUSB_SWAVE },
+
        { }     /* Terminating entry */
 };
 
@@ -333,12 +354,15 @@ static const struct usb_device_id blacklist_table[] = {
 #define BTUSB_FIRMWARE_LOADED  7
 #define BTUSB_FIRMWARE_FAILED  8
 #define BTUSB_BOOTING          9
+#define BTUSB_RESET_RESUME     10
+#define BTUSB_DIAG_RUNNING     11
 
 struct btusb_data {
        struct hci_dev       *hdev;
        struct usb_device    *udev;
        struct usb_interface *intf;
        struct usb_interface *isoc;
+       struct usb_interface *diag;
 
        unsigned long flags;
 
@@ -353,6 +377,7 @@ struct btusb_data {
        struct usb_anchor intr_anchor;
        struct usb_anchor bulk_anchor;
        struct usb_anchor isoc_anchor;
+       struct usb_anchor diag_anchor;
        spinlock_t rxlock;
 
        struct sk_buff *evt_skb;
@@ -364,6 +389,8 @@ struct btusb_data {
        struct usb_endpoint_descriptor *bulk_rx_ep;
        struct usb_endpoint_descriptor *isoc_tx_ep;
        struct usb_endpoint_descriptor *isoc_rx_ep;
+       struct usb_endpoint_descriptor *diag_tx_ep;
+       struct usb_endpoint_descriptor *diag_rx_ep;
 
        __u8 cmdreq_type;
        __u8 cmdreq;
@@ -861,6 +888,92 @@ static int btusb_submit_isoc_urb(struct hci_dev *hdev, gfp_t mem_flags)
        return err;
 }
 
+static void btusb_diag_complete(struct urb *urb)
+{
+       struct hci_dev *hdev = urb->context;
+       struct btusb_data *data = hci_get_drvdata(hdev);
+       int err;
+
+       BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status,
+              urb->actual_length);
+
+       if (urb->status == 0) {
+               struct sk_buff *skb;
+
+               skb = bt_skb_alloc(urb->actual_length, GFP_ATOMIC);
+               if (skb) {
+                       memcpy(skb_put(skb, urb->actual_length),
+                              urb->transfer_buffer, urb->actual_length);
+                       hci_recv_diag(hdev, skb);
+               }
+       } else if (urb->status == -ENOENT) {
+               /* Avoid suspend failed when usb_kill_urb */
+               return;
+       }
+
+       if (!test_bit(BTUSB_DIAG_RUNNING, &data->flags))
+               return;
+
+       usb_anchor_urb(urb, &data->diag_anchor);
+       usb_mark_last_busy(data->udev);
+
+       err = usb_submit_urb(urb, GFP_ATOMIC);
+       if (err < 0) {
+               /* -EPERM: urb is being killed;
+                * -ENODEV: device got disconnected */
+               if (err != -EPERM && err != -ENODEV)
+                       BT_ERR("%s urb %p failed to resubmit (%d)",
+                              hdev->name, urb, -err);
+               usb_unanchor_urb(urb);
+       }
+}
+
+static int btusb_submit_diag_urb(struct hci_dev *hdev, gfp_t mem_flags)
+{
+       struct btusb_data *data = hci_get_drvdata(hdev);
+       struct urb *urb;
+       unsigned char *buf;
+       unsigned int pipe;
+       int err, size = HCI_MAX_FRAME_SIZE;
+
+       BT_DBG("%s", hdev->name);
+
+       if (!data->diag_rx_ep)
+               return -ENODEV;
+
+       urb = usb_alloc_urb(0, mem_flags);
+       if (!urb)
+               return -ENOMEM;
+
+       buf = kmalloc(size, mem_flags);
+       if (!buf) {
+               usb_free_urb(urb);
+               return -ENOMEM;
+       }
+
+       pipe = usb_rcvbulkpipe(data->udev, data->diag_rx_ep->bEndpointAddress);
+
+       usb_fill_bulk_urb(urb, data->udev, pipe, buf, size,
+                         btusb_diag_complete, hdev);
+
+       urb->transfer_flags |= URB_FREE_BUFFER;
+
+       usb_mark_last_busy(data->udev);
+       usb_anchor_urb(urb, &data->diag_anchor);
+
+       err = usb_submit_urb(urb, mem_flags);
+       if (err < 0) {
+               if (err != -EPERM && err != -ENODEV)
+                       BT_ERR("%s urb %p submission failed (%d)",
+                              hdev->name, urb, -err);
+               usb_unanchor_urb(urb);
+       }
+
+       usb_free_urb(urb);
+
+       return err;
+}
+
 static void btusb_tx_complete(struct urb *urb)
 {
        struct sk_buff *skb = urb->context;
@@ -932,9 +1045,6 @@ static int btusb_open(struct hci_dev *hdev)
 
        data->intf->needs_remote_wakeup = 1;
 
-       if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
-               goto done;
-
        if (test_and_set_bit(BTUSB_INTR_RUNNING, &data->flags))
                goto done;
 
@@ -951,13 +1061,17 @@ static int btusb_open(struct hci_dev *hdev)
        set_bit(BTUSB_BULK_RUNNING, &data->flags);
        btusb_submit_bulk_urb(hdev, GFP_KERNEL);
 
+       if (data->diag) {
+               if (!btusb_submit_diag_urb(hdev, GFP_KERNEL))
+                       set_bit(BTUSB_DIAG_RUNNING, &data->flags);
+       }
+
 done:
        usb_autopm_put_interface(data->intf);
        return 0;
 
 failed:
        clear_bit(BTUSB_INTR_RUNNING, &data->flags);
-       clear_bit(HCI_RUNNING, &hdev->flags);
        usb_autopm_put_interface(data->intf);
        return err;
 }
@@ -967,6 +1081,7 @@ static void btusb_stop_traffic(struct btusb_data *data)
        usb_kill_anchored_urbs(&data->intr_anchor);
        usb_kill_anchored_urbs(&data->bulk_anchor);
        usb_kill_anchored_urbs(&data->isoc_anchor);
+       usb_kill_anchored_urbs(&data->diag_anchor);
 }
 
 static int btusb_close(struct hci_dev *hdev)
@@ -976,15 +1091,13 @@ static int btusb_close(struct hci_dev *hdev)
 
        BT_DBG("%s", hdev->name);
 
-       if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
-               return 0;
-
        cancel_work_sync(&data->work);
        cancel_work_sync(&data->waker);
 
        clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
        clear_bit(BTUSB_BULK_RUNNING, &data->flags);
        clear_bit(BTUSB_INTR_RUNNING, &data->flags);
+       clear_bit(BTUSB_DIAG_RUNNING, &data->flags);
 
        btusb_stop_traffic(data);
        btusb_free_frags(data);
@@ -1148,9 +1261,6 @@ static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
 
        BT_DBG("%s", hdev->name);
 
-       if (!test_bit(HCI_RUNNING, &hdev->flags))
-               return -EBUSY;
-
        switch (bt_cb(skb)->pkt_type) {
        case HCI_COMMAND_PKT:
                urb = alloc_ctrl_urb(hdev, skb);
@@ -1266,9 +1376,25 @@ static void btusb_work(struct work_struct *work)
                }
 
                if (data->isoc_altsetting != new_alts) {
+                       unsigned long flags;
+
                        clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
                        usb_kill_anchored_urbs(&data->isoc_anchor);
 
+                       /* When isochronous alternate setting needs to be
+                        * changed, because SCO connection has been added
+                        * or removed, a packet fragment may be left in the
+                        * reassembling state. This could lead to wrongly
+                        * assembled fragments.
+                        *
+                        * Clear outstanding fragment when selecting a new
+                        * alternate setting.
+                        */
+                       spin_lock_irqsave(&data->rxlock, flags);
+                       kfree_skb(data->sco_skb);
+                       data->sco_skb = NULL;
+                       spin_unlock_irqrestore(&data->rxlock, flags);
+
                        if (__set_isoc_interface(hdev, new_alts) < 0)
                                return;
                }
@@ -1301,28 +1427,6 @@ static void btusb_waker(struct work_struct *work)
        usb_autopm_put_interface(data->intf);
 }
 
-static struct sk_buff *btusb_read_local_version(struct hci_dev *hdev)
-{
-       struct sk_buff *skb;
-
-       skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL,
-                            HCI_INIT_TIMEOUT);
-       if (IS_ERR(skb)) {
-               BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION failed (%ld)",
-                      hdev->name, PTR_ERR(skb));
-               return skb;
-       }
-
-       if (skb->len != sizeof(struct hci_rp_read_local_version)) {
-               BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION event length mismatch",
-                      hdev->name);
-               kfree_skb(skb);
-               return ERR_PTR(-EIO);
-       }
-
-       return skb;
-}
-
 static int btusb_setup_bcm92035(struct hci_dev *hdev)
 {
        struct sk_buff *skb;
@@ -1343,408 +1447,42 @@ static int btusb_setup_csr(struct hci_dev *hdev)
 {
        struct hci_rp_read_local_version *rp;
        struct sk_buff *skb;
-       int ret;
 
        BT_DBG("%s", hdev->name);
 
-       skb = btusb_read_local_version(hdev);
-       if (IS_ERR(skb))
-               return -PTR_ERR(skb);
-
-       rp = (struct hci_rp_read_local_version *)skb->data;
-
-       if (!rp->status) {
-               if (le16_to_cpu(rp->manufacturer) != 10) {
-                       /* Clear the reset quirk since this is not an actual
-                        * early Bluetooth 1.1 device from CSR.
-                        */
-                       clear_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
-
-                       /* These fake CSR controllers have all a broken
-                        * stored link key handling and so just disable it.
-                        */
-                       set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY,
-                               &hdev->quirks);
-               }
-       }
-
-       ret = -bt_to_errno(rp->status);
-
-       kfree_skb(skb);
-
-       return ret;
-}
-
-#define RTL_FRAG_LEN 252
-
-struct rtl_download_cmd {
-       __u8 index;
-       __u8 data[RTL_FRAG_LEN];
-} __packed;
-
-struct rtl_download_response {
-       __u8 status;
-       __u8 index;
-} __packed;
-
-struct rtl_rom_version_evt {
-       __u8 status;
-       __u8 version;
-} __packed;
-
-struct rtl_epatch_header {
-       __u8 signature[8];
-       __le32 fw_version;
-       __le16 num_patches;
-} __packed;
-
-#define RTL_EPATCH_SIGNATURE   "Realtech"
-#define RTL_ROM_LMP_3499       0x3499
-#define RTL_ROM_LMP_8723A      0x1200
-#define RTL_ROM_LMP_8723B      0x8723
-#define RTL_ROM_LMP_8821A      0x8821
-#define RTL_ROM_LMP_8761A      0x8761
-
-static int rtl_read_rom_version(struct hci_dev *hdev, u8 *version)
-{
-       struct rtl_rom_version_evt *rom_version;
-       struct sk_buff *skb;
-       int ret;
-
-       /* Read RTL ROM version command */
-       skb = __hci_cmd_sync(hdev, 0xfc6d, 0, NULL, HCI_INIT_TIMEOUT);
+       skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL,
+                            HCI_INIT_TIMEOUT);
        if (IS_ERR(skb)) {
-               BT_ERR("%s: Read ROM version failed (%ld)",
-                      hdev->name, PTR_ERR(skb));
-               return PTR_ERR(skb);
+               int err = PTR_ERR(skb);
+               BT_ERR("%s: CSR: Local version failed (%d)", hdev->name, err);
+               return err;
        }
 
-       if (skb->len != sizeof(*rom_version)) {
-               BT_ERR("%s: RTL version event length mismatch", hdev->name);
+       if (skb->len != sizeof(struct hci_rp_read_local_version)) {
+               BT_ERR("%s: CSR: Local version length mismatch", hdev->name);
                kfree_skb(skb);
                return -EIO;
        }
 
-       rom_version = (struct rtl_rom_version_evt *)skb->data;
-       BT_INFO("%s: rom_version status=%x version=%x",
-               hdev->name, rom_version->status, rom_version->version);
-
-       ret = rom_version->status;
-       if (ret == 0)
-               *version = rom_version->version;
-
-       kfree_skb(skb);
-       return ret;
-}
-
-static int rtl8723b_parse_firmware(struct hci_dev *hdev, u16 lmp_subver,
-                                  const struct firmware *fw,
-                                  unsigned char **_buf)
-{
-       const u8 extension_sig[] = { 0x51, 0x04, 0xfd, 0x77 };
-       struct rtl_epatch_header *epatch_info;
-       unsigned char *buf;
-       int i, ret, len;
-       size_t min_size;
-       u8 opcode, length, data, rom_version = 0;
-       int project_id = -1;
-       const unsigned char *fwptr, *chip_id_base;
-       const unsigned char *patch_length_base, *patch_offset_base;
-       u32 patch_offset = 0;
-       u16 patch_length, num_patches;
-       const u16 project_id_to_lmp_subver[] = {
-               RTL_ROM_LMP_8723A,
-               RTL_ROM_LMP_8723B,
-               RTL_ROM_LMP_8821A,
-               RTL_ROM_LMP_8761A
-       };
-
-       ret = rtl_read_rom_version(hdev, &rom_version);
-       if (ret)
-               return -bt_to_errno(ret);
-
-       min_size = sizeof(struct rtl_epatch_header) + sizeof(extension_sig) + 3;
-       if (fw->size < min_size)
-               return -EINVAL;
-
-       fwptr = fw->data + fw->size - sizeof(extension_sig);
-       if (memcmp(fwptr, extension_sig, sizeof(extension_sig)) != 0) {
-               BT_ERR("%s: extension section signature mismatch", hdev->name);
-               return -EINVAL;
-       }
-
-       /* Loop from the end of the firmware parsing instructions, until
-        * we find an instruction that identifies the "project ID" for the
-        * hardware supported by this firwmare file.
-        * Once we have that, we double-check that that project_id is suitable
-        * for the hardware we are working with.
-        */
-       while (fwptr >= fw->data + (sizeof(struct rtl_epatch_header) + 3)) {
-               opcode = *--fwptr;
-               length = *--fwptr;
-               data = *--fwptr;
-
-               BT_DBG("check op=%x len=%x data=%x", opcode, length, data);
-
-               if (opcode == 0xff) /* EOF */
-                       break;
-
-               if (length == 0) {
-                       BT_ERR("%s: found instruction with length 0",
-                              hdev->name);
-                       return -EINVAL;
-               }
-
-               if (opcode == 0 && length == 1) {
-                       project_id = data;
-                       break;
-               }
-
-               fwptr -= length;
-       }
-
-       if (project_id < 0) {
-               BT_ERR("%s: failed to find version instruction", hdev->name);
-               return -EINVAL;
-       }
-
-       if (project_id >= ARRAY_SIZE(project_id_to_lmp_subver)) {
-               BT_ERR("%s: unknown project id %d", hdev->name, project_id);
-               return -EINVAL;
-       }
-
-       if (lmp_subver != project_id_to_lmp_subver[project_id]) {
-               BT_ERR("%s: firmware is for %x but this is a %x", hdev->name,
-                      project_id_to_lmp_subver[project_id], lmp_subver);
-               return -EINVAL;
-       }
-
-       epatch_info = (struct rtl_epatch_header *)fw->data;
-       if (memcmp(epatch_info->signature, RTL_EPATCH_SIGNATURE, 8) != 0) {
-               BT_ERR("%s: bad EPATCH signature", hdev->name);
-               return -EINVAL;
-       }
-
-       num_patches = le16_to_cpu(epatch_info->num_patches);
-       BT_DBG("fw_version=%x, num_patches=%d",
-              le32_to_cpu(epatch_info->fw_version), num_patches);
-
-       /* After the rtl_epatch_header there is a funky patch metadata section.
-        * Assuming 2 patches, the layout is:
-        * ChipID1 ChipID2 PatchLength1 PatchLength2 PatchOffset1 PatchOffset2
-        *
-        * Find the right patch for this chip.
-        */
-       min_size += 8 * num_patches;
-       if (fw->size < min_size)
-               return -EINVAL;
-
-       chip_id_base = fw->data + sizeof(struct rtl_epatch_header);
-       patch_length_base = chip_id_base + (sizeof(u16) * num_patches);
-       patch_offset_base = patch_length_base + (sizeof(u16) * num_patches);
-       for (i = 0; i < num_patches; i++) {
-               u16 chip_id = get_unaligned_le16(chip_id_base +
-                                                (i * sizeof(u16)));
-               if (chip_id == rom_version + 1) {
-                       patch_length = get_unaligned_le16(patch_length_base +
-                                                         (i * sizeof(u16)));
-                       patch_offset = get_unaligned_le32(patch_offset_base +
-                                                         (i * sizeof(u32)));
-                       break;
-               }
-       }
-
-       if (!patch_offset) {
-               BT_ERR("%s: didn't find patch for chip id %d",
-                      hdev->name, rom_version);
-               return -EINVAL;
-       }
-
-       BT_DBG("length=%x offset=%x index %d", patch_length, patch_offset, i);
-       min_size = patch_offset + patch_length;
-       if (fw->size < min_size)
-               return -EINVAL;
-
-       /* Copy the firmware into a new buffer and write the version at
-        * the end.
-        */
-       len = patch_length;
-       buf = kmemdup(fw->data + patch_offset, patch_length, GFP_KERNEL);
-       if (!buf)
-               return -ENOMEM;
-
-       memcpy(buf + patch_length - 4, &epatch_info->fw_version, 4);
-
-       *_buf = buf;
-       return len;
-}
-
-static int rtl_download_firmware(struct hci_dev *hdev,
-                                const unsigned char *data, int fw_len)
-{
-       struct rtl_download_cmd *dl_cmd;
-       int frag_num = fw_len / RTL_FRAG_LEN + 1;
-       int frag_len = RTL_FRAG_LEN;
-       int ret = 0;
-       int i;
-
-       dl_cmd = kmalloc(sizeof(struct rtl_download_cmd), GFP_KERNEL);
-       if (!dl_cmd)
-               return -ENOMEM;
-
-       for (i = 0; i < frag_num; i++) {
-               struct rtl_download_response *dl_resp;
-               struct sk_buff *skb;
-
-               BT_DBG("download fw (%d/%d)", i, frag_num);
-
-               dl_cmd->index = i;
-               if (i == (frag_num - 1)) {
-                       dl_cmd->index |= 0x80; /* data end */
-                       frag_len = fw_len % RTL_FRAG_LEN;
-               }
-               memcpy(dl_cmd->data, data, frag_len);
-
-               /* Send download command */
-               skb = __hci_cmd_sync(hdev, 0xfc20, frag_len + 1, dl_cmd,
-                                    HCI_INIT_TIMEOUT);
-               if (IS_ERR(skb)) {
-                       BT_ERR("%s: download fw command failed (%ld)",
-                              hdev->name, PTR_ERR(skb));
-                       ret = -PTR_ERR(skb);
-                       goto out;
-               }
-
-               if (skb->len != sizeof(*dl_resp)) {
-                       BT_ERR("%s: download fw event length mismatch",
-                              hdev->name);
-                       kfree_skb(skb);
-                       ret = -EIO;
-                       goto out;
-               }
-
-               dl_resp = (struct rtl_download_response *)skb->data;
-               if (dl_resp->status != 0) {
-                       kfree_skb(skb);
-                       ret = bt_to_errno(dl_resp->status);
-                       goto out;
-               }
-
-               kfree_skb(skb);
-               data += RTL_FRAG_LEN;
-       }
-
-out:
-       kfree(dl_cmd);
-       return ret;
-}
-
-static int btusb_setup_rtl8723a(struct hci_dev *hdev)
-{
-       struct btusb_data *data = dev_get_drvdata(&hdev->dev);
-       struct usb_device *udev = interface_to_usbdev(data->intf);
-       const struct firmware *fw;
-       int ret;
-
-       BT_INFO("%s: rtl: loading rtl_bt/rtl8723a_fw.bin", hdev->name);
-       ret = request_firmware(&fw, "rtl_bt/rtl8723a_fw.bin", &udev->dev);
-       if (ret < 0) {
-               BT_ERR("%s: Failed to load rtl_bt/rtl8723a_fw.bin", hdev->name);
-               return ret;
-       }
-
-       if (fw->size < 8) {
-               ret = -EINVAL;
-               goto out;
-       }
-
-       /* Check that the firmware doesn't have the epatch signature
-        * (which is only for RTL8723B and newer).
-        */
-       if (!memcmp(fw->data, RTL_EPATCH_SIGNATURE, 8)) {
-               BT_ERR("%s: unexpected EPATCH signature!", hdev->name);
-               ret = -EINVAL;
-               goto out;
-       }
-
-       ret = rtl_download_firmware(hdev, fw->data, fw->size);
-
-out:
-       release_firmware(fw);
-       return ret;
-}
+       rp = (struct hci_rp_read_local_version *)skb->data;
 
-static int btusb_setup_rtl8723b(struct hci_dev *hdev, u16 lmp_subver,
-                               const char *fw_name)
-{
-       struct btusb_data *data = dev_get_drvdata(&hdev->dev);
-       struct usb_device *udev = interface_to_usbdev(data->intf);
-       unsigned char *fw_data = NULL;
-       const struct firmware *fw;
-       int ret;
+       /* Detect controllers which aren't real CSR ones. */
+       if (le16_to_cpu(rp->manufacturer) != 10 ||
+           le16_to_cpu(rp->lmp_subver) == 0x0c5c) {
+               /* Clear the reset quirk since this is not an actual
+                * early Bluetooth 1.1 device from CSR.
+                */
+               clear_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
 
-       BT_INFO("%s: rtl: loading %s", hdev->name, fw_name);
-       ret = request_firmware(&fw, fw_name, &udev->dev);
-       if (ret < 0) {
-               BT_ERR("%s: Failed to load %s", hdev->name, fw_name);
-               return ret;
+               /* These fake CSR controllers have all a broken
+                * stored link key handling and so just disable it.
+                */
+               set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks);
        }
 
-       ret = rtl8723b_parse_firmware(hdev, lmp_subver, fw, &fw_data);
-       if (ret < 0)
-               goto out;
-
-       ret = rtl_download_firmware(hdev, fw_data, ret);
-       kfree(fw_data);
-       if (ret < 0)
-               goto out;
-
-out:
-       release_firmware(fw);
-       return ret;
-}
-
-static int btusb_setup_realtek(struct hci_dev *hdev)
-{
-       struct sk_buff *skb;
-       struct hci_rp_read_local_version *resp;
-       u16 lmp_subver;
-
-       skb = btusb_read_local_version(hdev);
-       if (IS_ERR(skb))
-               return -PTR_ERR(skb);
-
-       resp = (struct hci_rp_read_local_version *)skb->data;
-       BT_INFO("%s: rtl: examining hci_ver=%02x hci_rev=%04x lmp_ver=%02x "
-               "lmp_subver=%04x", hdev->name, resp->hci_ver, resp->hci_rev,
-               resp->lmp_ver, resp->lmp_subver);
-
-       lmp_subver = le16_to_cpu(resp->lmp_subver);
        kfree_skb(skb);
 
-       /* Match a set of subver values that correspond to stock firmware,
-        * which is not compatible with standard btusb.
-        * If matched, upload an alternative firmware that does conform to
-        * standard btusb. Once that firmware is uploaded, the subver changes
-        * to a different value.
-        */
-       switch (lmp_subver) {
-       case RTL_ROM_LMP_8723A:
-       case RTL_ROM_LMP_3499:
-               return btusb_setup_rtl8723a(hdev);
-       case RTL_ROM_LMP_8723B:
-               return btusb_setup_rtl8723b(hdev, lmp_subver,
-                                           "rtl_bt/rtl8723b_fw.bin");
-       case RTL_ROM_LMP_8821A:
-               return btusb_setup_rtl8723b(hdev, lmp_subver,
-                                           "rtl_bt/rtl8821a_fw.bin");
-       case RTL_ROM_LMP_8761A:
-               return btusb_setup_rtl8723b(hdev, lmp_subver,
-                                           "rtl_bt/rtl8761a_fw.bin");
-       default:
-               BT_INFO("rtl: assuming no firmware upload needed.");
-               return 0;
-       }
+       return 0;
 }
 
 static const struct firmware *btusb_setup_intel_get_fw(struct hci_dev *hdev,
@@ -1954,12 +1692,6 @@ static int btusb_setup_intel(struct hci_dev *hdev)
        }
 
        ver = (struct intel_version *)skb->data;
-       if (ver->status) {
-               BT_ERR("%s Intel fw version event failed (%02x)", hdev->name,
-                      ver->status);
-               kfree_skb(skb);
-               return -bt_to_errno(ver->status);
-       }
 
        BT_INFO("%s: read Intel version: %02x%02x%02x%02x%02x%02x%02x%02x%02x",
                hdev->name, ver->hw_platform, ver->hw_variant,
@@ -1969,14 +1701,13 @@ static int btusb_setup_intel(struct hci_dev *hdev)
 
        /* fw_patch_num indicates the version of patch the device currently
         * have. If there is no patch data in the device, it is always 0x00.
-        * So, if it is other than 0x00, no need to patch the deivce again.
+        * So, if it is other than 0x00, no need to patch the device again.
         */
        if (ver->fw_patch_num) {
                BT_INFO("%s: Intel device is already patched. patch num: %02x",
                        hdev->name, ver->fw_patch_num);
                kfree_skb(skb);
-               btintel_check_bdaddr(hdev);
-               return 0;
+               goto complete;
        }
 
        /* Opens the firmware patch file based on the firmware version read
@@ -1988,8 +1719,7 @@ static int btusb_setup_intel(struct hci_dev *hdev)
        fw = btusb_setup_intel_get_fw(hdev, ver);
        if (!fw) {
                kfree_skb(skb);
-               btintel_check_bdaddr(hdev);
-               return 0;
+               goto complete;
        }
        fw_ptr = fw->data;
 
@@ -2009,15 +1739,6 @@ static int btusb_setup_intel(struct hci_dev *hdev)
                return PTR_ERR(skb);
        }
 
-       if (skb->data[0]) {
-               u8 evt_status = skb->data[0];
-
-               BT_ERR("%s enable Intel manufacturer mode event failed (%02x)",
-                      hdev->name, evt_status);
-               kfree_skb(skb);
-               release_firmware(fw);
-               return -bt_to_errno(evt_status);
-       }
        kfree_skb(skb);
 
        disable_patch = 1;
@@ -2071,8 +1792,7 @@ static int btusb_setup_intel(struct hci_dev *hdev)
        BT_INFO("%s: Intel Bluetooth firmware patch completed and activated",
                hdev->name);
 
-       btintel_check_bdaddr(hdev);
-       return 0;
+       goto complete;
 
 exit_mfg_disable:
        /* Disable the manufacturer mode without reset */
@@ -2087,8 +1807,7 @@ exit_mfg_disable:
 
        BT_INFO("%s: Intel Bluetooth firmware patch completed", hdev->name);
 
-       btintel_check_bdaddr(hdev);
-       return 0;
+       goto complete;
 
 exit_mfg_deactivate:
        release_firmware(fw);
@@ -2108,6 +1827,12 @@ exit_mfg_deactivate:
        BT_INFO("%s: Intel Bluetooth firmware patch completed and deactivated",
                hdev->name);
 
+complete:
+       /* Set the event mask for Intel specific vendor events. This enables
+        * a few extra events that are useful during general operation.
+        */
+       btintel_set_event_mask_mfg(hdev, false);
+
        btintel_check_bdaddr(hdev);
        return 0;
 }
@@ -2224,9 +1949,6 @@ static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb)
 
        BT_DBG("%s", hdev->name);
 
-       if (!test_bit(HCI_RUNNING, &hdev->flags))
-               return -EBUSY;
-
        switch (bt_cb(skb)->pkt_type) {
        case HCI_COMMAND_PKT:
                if (test_bit(BTUSB_BOOTLOADER, &data->flags)) {
@@ -2281,51 +2003,6 @@ static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb)
        return -EILSEQ;
 }
 
-static int btusb_intel_secure_send(struct hci_dev *hdev, u8 fragment_type,
-                                  u32 plen, const void *param)
-{
-       while (plen > 0) {
-               struct sk_buff *skb;
-               u8 cmd_param[253], fragment_len = (plen > 252) ? 252 : plen;
-
-               cmd_param[0] = fragment_type;
-               memcpy(cmd_param + 1, param, fragment_len);
-
-               skb = __hci_cmd_sync(hdev, 0xfc09, fragment_len + 1,
-                                    cmd_param, HCI_INIT_TIMEOUT);
-               if (IS_ERR(skb))
-                       return PTR_ERR(skb);
-
-               kfree_skb(skb);
-
-               plen -= fragment_len;
-               param += fragment_len;
-       }
-
-       return 0;
-}
-
-static void btusb_intel_version_info(struct hci_dev *hdev,
-                                    struct intel_version *ver)
-{
-       const char *variant;
-
-       switch (ver->fw_variant) {
-       case 0x06:
-               variant = "Bootloader";
-               break;
-       case 0x23:
-               variant = "Firmware";
-               break;
-       default:
-               return;
-       }
-
-       BT_INFO("%s: %s revision %u.%u build %u week %u %u", hdev->name,
-               variant, ver->fw_revision >> 4, ver->fw_revision & 0x0f,
-               ver->fw_build_num, ver->fw_build_ww, 2000 + ver->fw_build_yy);
-}
-
 static int btusb_setup_intel_new(struct hci_dev *hdev)
 {
        static const u8 reset_param[] = { 0x00, 0x01, 0x00, 0x01,
@@ -2364,13 +2041,6 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
        }
 
        ver = (struct intel_version *)skb->data;
-       if (ver->status) {
-               BT_ERR("%s: Intel version command failure (%02x)",
-                      hdev->name, ver->status);
-               err = -bt_to_errno(ver->status);
-               kfree_skb(skb);
-               return err;
-       }
 
        /* The hardware platform number has a fixed value of 0x37 and
         * for now only accept this single value.
@@ -2394,7 +2064,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
                return -EINVAL;
        }
 
-       btusb_intel_version_info(hdev, ver);
+       btintel_version_info(hdev, ver);
 
        /* The firmware variant determines if the device is in bootloader
         * mode or is running operational firmware. The value 0x06 identifies
@@ -2445,13 +2115,6 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
        }
 
        params = (struct intel_boot_params *)skb->data;
-       if (params->status) {
-               BT_ERR("%s: Intel boot parameters command failure (%02x)",
-                      hdev->name, params->status);
-               err = -bt_to_errno(params->status);
-               kfree_skb(skb);
-               return err;
-       }
 
        BT_INFO("%s: Device revision is %u", hdev->name,
                le16_to_cpu(params->dev_revid));
@@ -2459,6 +2122,15 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
        BT_INFO("%s: Secure boot is %s", hdev->name,
                params->secure_boot ? "enabled" : "disabled");
 
+       BT_INFO("%s: OTP lock is %s", hdev->name,
+               params->otp_lock ? "enabled" : "disabled");
+
+       BT_INFO("%s: API lock is %s", hdev->name,
+               params->api_lock ? "enabled" : "disabled");
+
+       BT_INFO("%s: Debug lock is %s", hdev->name,
+               params->debug_lock ? "enabled" : "disabled");
+
        BT_INFO("%s: Minimum firmware build %u week %u %u", hdev->name,
                params->min_fw_build_nn, params->min_fw_build_cw,
                2000 + params->min_fw_build_yy);
@@ -2501,6 +2173,12 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
 
        BT_INFO("%s: Found device firmware: %s", hdev->name, fwname);
 
+       /* Save the DDC file name for later use to apply once the firmware
+        * downloading is done.
+        */
+       snprintf(fwname, sizeof(fwname), "intel/ibt-11-%u.ddc",
+                le16_to_cpu(params->dev_revid));
+
        kfree_skb(skb);
 
        if (fw->size < 644) {
@@ -2515,7 +2193,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
        /* Start the firmware download transaction with the Init fragment
         * represented by the 128 bytes of CSS header.
         */
-       err = btusb_intel_secure_send(hdev, 0x00, 128, fw->data);
+       err = btintel_secure_send(hdev, 0x00, 128, fw->data);
        if (err < 0) {
                BT_ERR("%s: Failed to send firmware header (%d)",
                       hdev->name, err);
@@ -2525,7 +2203,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
        /* Send the 256 bytes of public key information from the firmware
         * as the PKey fragment.
         */
-       err = btusb_intel_secure_send(hdev, 0x03, 256, fw->data + 128);
+       err = btintel_secure_send(hdev, 0x03, 256, fw->data + 128);
        if (err < 0) {
                BT_ERR("%s: Failed to send firmware public key (%d)",
                       hdev->name, err);
@@ -2535,7 +2213,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
        /* Send the 256 bytes of signature information from the firmware
         * as the Sign fragment.
         */
-       err = btusb_intel_secure_send(hdev, 0x02, 256, fw->data + 388);
+       err = btintel_secure_send(hdev, 0x02, 256, fw->data + 388);
        if (err < 0) {
                BT_ERR("%s: Failed to send firmware signature (%d)",
                       hdev->name, err);
@@ -2550,7 +2228,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
 
                frag_len += sizeof(*cmd) + cmd->plen;
 
-               /* The paramter length of the secure send command requires
+               /* The parameter length of the secure send command requires
                 * a 4 byte alignment. It happens so that the firmware file
                 * contains proper Intel_NOP commands to align the fragments
                 * as needed.
@@ -2559,8 +2237,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
                 * firmware data buffer as a single Data fragement.
                 */
                if (!(frag_len % 4)) {
-                       err = btusb_intel_secure_send(hdev, 0x01, frag_len,
-                                                     fw_ptr);
+                       err = btintel_secure_send(hdev, 0x01, frag_len, fw_ptr);
                        if (err < 0) {
                                BT_ERR("%s: Failed to send firmware data (%d)",
                                       hdev->name, err);
@@ -2662,47 +2339,24 @@ done:
 
        clear_bit(BTUSB_BOOTLOADER, &data->flags);
 
-       return 0;
-}
-
-static void btusb_hw_error_intel(struct hci_dev *hdev, u8 code)
-{
-       struct sk_buff *skb;
-       u8 type = 0x00;
-
-       BT_ERR("%s: Hardware error 0x%2.2x", hdev->name, code);
-
-       skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
-       if (IS_ERR(skb)) {
-               BT_ERR("%s: Reset after hardware error failed (%ld)",
-                      hdev->name, PTR_ERR(skb));
-               return;
-       }
-       kfree_skb(skb);
-
-       skb = __hci_cmd_sync(hdev, 0xfc22, 1, &type, HCI_INIT_TIMEOUT);
-       if (IS_ERR(skb)) {
-               BT_ERR("%s: Retrieving Intel exception info failed (%ld)",
-                      hdev->name, PTR_ERR(skb));
-               return;
-       }
-
-       if (skb->len != 13) {
-               BT_ERR("%s: Exception info size mismatch", hdev->name);
-               kfree_skb(skb);
-               return;
-       }
-
-       if (skb->data[0] != 0x00) {
-               BT_ERR("%s: Exception info command failure (%02x)",
-                      hdev->name, skb->data[0]);
-               kfree_skb(skb);
-               return;
-       }
+       /* Once the device is running in operational mode, it needs to apply
+        * the device configuration (DDC) parameters.
+        *
+        * The device can work without DDC parameters, so even if it fails
+        * to load the file, no need to fail the setup.
+        */
+       btintel_load_ddc_config(hdev, fwname);
 
-       BT_ERR("%s: Exception info %s", hdev->name, (char *)(skb->data + 1));
+       /* Set the event mask for Intel specific vendor events. This enables
+        * a few extra events that are useful during general operation. It
+        * does not enable any debugging related events.
+        *
+        * The device will function correctly without these events enabled
+        * and thus no need to fail the setup.
+        */
+       btintel_set_event_mask(hdev, false);
 
-       kfree_skb(skb);
+       return 0;
 }
 
 static int btusb_shutdown_intel(struct hci_dev *hdev)
@@ -2807,6 +2461,7 @@ struct qca_device_info {
 static const struct qca_device_info qca_devices_table[] = {
        { 0x00000100, 20, 4, 10 }, /* Rome 1.0 */
        { 0x00000101, 20, 4, 10 }, /* Rome 1.1 */
+       { 0x00000200, 28, 4, 18 }, /* Rome 2.0 */
        { 0x00000201, 28, 4, 18 }, /* Rome 2.1 */
        { 0x00000300, 28, 4, 18 }, /* Rome 3.0 */
        { 0x00000302, 28, 4, 18 }, /* Rome 3.2 */
@@ -3026,19 +2681,115 @@ static int btusb_setup_qca(struct hci_dev *hdev)
        return 0;
 }
 
+#ifdef CONFIG_BT_HCIBTUSB_BCM
+static inline int __set_diag_interface(struct hci_dev *hdev)
+{
+       struct btusb_data *data = hci_get_drvdata(hdev);
+       struct usb_interface *intf = data->diag;
+       int i;
+
+       if (!data->diag)
+               return -ENODEV;
+
+       data->diag_tx_ep = NULL;
+       data->diag_rx_ep = NULL;
+
+       for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
+               struct usb_endpoint_descriptor *ep_desc;
+
+               ep_desc = &intf->cur_altsetting->endpoint[i].desc;
+
+               if (!data->diag_tx_ep && usb_endpoint_is_bulk_out(ep_desc)) {
+                       data->diag_tx_ep = ep_desc;
+                       continue;
+               }
+
+               if (!data->diag_rx_ep && usb_endpoint_is_bulk_in(ep_desc)) {
+                       data->diag_rx_ep = ep_desc;
+                       continue;
+               }
+       }
+
+       if (!data->diag_tx_ep || !data->diag_rx_ep) {
+               BT_ERR("%s invalid diagnostic descriptors", hdev->name);
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static struct urb *alloc_diag_urb(struct hci_dev *hdev, bool enable)
+{
+       struct btusb_data *data = hci_get_drvdata(hdev);
+       struct sk_buff *skb;
+       struct urb *urb;
+       unsigned int pipe;
+
+       if (!data->diag_tx_ep)
+               return ERR_PTR(-ENODEV);
+
+       urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!urb)
+               return ERR_PTR(-ENOMEM);
+
+       skb = bt_skb_alloc(2, GFP_KERNEL);
+       if (!skb) {
+               usb_free_urb(urb);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       *skb_put(skb, 1) = 0xf0;
+       *skb_put(skb, 1) = enable;
+
+       pipe = usb_sndbulkpipe(data->udev, data->diag_tx_ep->bEndpointAddress);
+
+       usb_fill_bulk_urb(urb, data->udev, pipe,
+                         skb->data, skb->len, btusb_tx_complete, skb);
+
+       skb->dev = (void *)hdev;
+
+       return urb;
+}
+
+static int btusb_bcm_set_diag(struct hci_dev *hdev, bool enable)
+{
+       struct btusb_data *data = hci_get_drvdata(hdev);
+       struct urb *urb;
+
+       if (!data->diag)
+               return -ENODEV;
+
+       if (!test_bit(HCI_RUNNING, &hdev->flags))
+               return -ENETDOWN;
+
+       urb = alloc_diag_urb(hdev, enable);
+       if (IS_ERR(urb))
+               return PTR_ERR(urb);
+
+       return submit_or_queue_tx_urb(hdev, urb);
+}
+#endif
+
 static int btusb_probe(struct usb_interface *intf,
                       const struct usb_device_id *id)
 {
        struct usb_endpoint_descriptor *ep_desc;
        struct btusb_data *data;
        struct hci_dev *hdev;
+       unsigned ifnum_base;
        int i, err;
 
        BT_DBG("intf %p id %p", intf, id);
 
        /* interface numbers are hardcoded in the spec */
-       if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
-               return -ENODEV;
+       if (intf->cur_altsetting->desc.bInterfaceNumber != 0) {
+               if (!(id->driver_info & BTUSB_IFNUM_2))
+                       return -ENODEV;
+               if (intf->cur_altsetting->desc.bInterfaceNumber != 2)
+                       return -ENODEV;
+       }
+
+       ifnum_base = intf->cur_altsetting->desc.bInterfaceNumber;
 
        if (!id->driver_info) {
                const struct usb_device_id *match;
@@ -3106,6 +2857,7 @@ static int btusb_probe(struct usb_interface *intf,
        init_usb_anchor(&data->intr_anchor);
        init_usb_anchor(&data->bulk_anchor);
        init_usb_anchor(&data->isoc_anchor);
+       init_usb_anchor(&data->diag_anchor);
        spin_lock_init(&data->rxlock);
 
        if (id->driver_info & BTUSB_INTEL_NEW) {
@@ -3139,33 +2891,53 @@ static int btusb_probe(struct usb_interface *intf,
        hdev->send   = btusb_send_frame;
        hdev->notify = btusb_notify;
 
+       if (id->driver_info & BTUSB_BCM2045)
+               set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks);
+
        if (id->driver_info & BTUSB_BCM92035)
                hdev->setup = btusb_setup_bcm92035;
 
 #ifdef CONFIG_BT_HCIBTUSB_BCM
        if (id->driver_info & BTUSB_BCM_PATCHRAM) {
+               hdev->manufacturer = 15;
                hdev->setup = btbcm_setup_patchram;
+               hdev->set_diag = btusb_bcm_set_diag;
                hdev->set_bdaddr = btbcm_set_bdaddr;
+
+               /* Broadcom LM_DIAG Interface numbers are hardcoded */
+               data->diag = usb_ifnum_to_if(data->udev, ifnum_base + 2);
        }
 
-       if (id->driver_info & BTUSB_BCM_APPLE)
+       if (id->driver_info & BTUSB_BCM_APPLE) {
+               hdev->manufacturer = 15;
                hdev->setup = btbcm_setup_apple;
+               hdev->set_diag = btusb_bcm_set_diag;
+
+               /* Broadcom LM_DIAG Interface numbers are hardcoded */
+               data->diag = usb_ifnum_to_if(data->udev, ifnum_base + 2);
+       }
 #endif
 
        if (id->driver_info & BTUSB_INTEL) {
+               hdev->manufacturer = 2;
                hdev->setup = btusb_setup_intel;
                hdev->shutdown = btusb_shutdown_intel;
+               hdev->set_diag = btintel_set_diag_mfg;
                hdev->set_bdaddr = btintel_set_bdaddr;
                set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);
                set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
+               set_bit(HCI_QUIRK_NON_PERSISTENT_DIAG, &hdev->quirks);
        }
 
        if (id->driver_info & BTUSB_INTEL_NEW) {
+               hdev->manufacturer = 2;
                hdev->send = btusb_send_frame_intel;
                hdev->setup = btusb_setup_intel_new;
-               hdev->hw_error = btusb_hw_error_intel;
+               hdev->hw_error = btintel_hw_error;
+               hdev->set_diag = btintel_set_diag;
                hdev->set_bdaddr = btintel_set_bdaddr;
                set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);
+               set_bit(HCI_QUIRK_NON_PERSISTENT_DIAG, &hdev->quirks);
        }
 
        if (id->driver_info & BTUSB_MARVELL)
@@ -3176,8 +2948,10 @@ static int btusb_probe(struct usb_interface *intf,
                set_bit(HCI_QUIRK_BROKEN_LOCAL_COMMANDS, &hdev->quirks);
        }
 
-       if (id->driver_info & BTUSB_INTEL_BOOT)
+       if (id->driver_info & BTUSB_INTEL_BOOT) {
+               hdev->manufacturer = 2;
                set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
+       }
 
        if (id->driver_info & BTUSB_ATH3012) {
                hdev->set_bdaddr = btusb_set_bdaddr_ath3012;
@@ -3190,15 +2964,24 @@ static int btusb_probe(struct usb_interface *intf,
                hdev->set_bdaddr = btusb_set_bdaddr_ath3012;
        }
 
-       if (id->driver_info & BTUSB_REALTEK)
-               hdev->setup = btusb_setup_realtek;
+#ifdef CONFIG_BT_HCIBTUSB_RTL
+       if (id->driver_info & BTUSB_REALTEK) {
+               hdev->setup = btrtl_setup_realtek;
+
+               /* Realtek 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);
+       }
+#endif
 
        if (id->driver_info & BTUSB_AMP) {
                /* AMP controllers do not support SCO packets */
                data->isoc = NULL;
        } else {
-               /* Interface numbers are hardcoded in the specification */
-               data->isoc = usb_ifnum_to_if(data->udev, 1);
+               /* Interface orders are hardcoded in the specification */
+               data->isoc = usb_ifnum_to_if(data->udev, ifnum_base + 1);
        }
 
        if (!reset)
@@ -3226,7 +3009,7 @@ static int btusb_probe(struct usb_interface *intf,
                        set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
 
                /* Fake CSR devices with broken commands */
-               if (bcdDevice <= 0x100)
+               if (bcdDevice <= 0x100 || bcdDevice == 0x134)
                        hdev->setup = btusb_setup_csr;
 
                set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
@@ -3261,6 +3044,16 @@ static int btusb_probe(struct usb_interface *intf,
                }
        }
 
+#ifdef CONFIG_BT_HCIBTUSB_BCM
+       if (data->diag) {
+               if (!usb_driver_claim_interface(&btusb_driver,
+                                               data->diag, data))
+                       __set_diag_interface(hdev);
+               else
+                       data->diag = NULL;
+       }
+#endif
+
        err = hci_register_dev(hdev);
        if (err < 0) {
                hci_free_dev(hdev);
@@ -3288,12 +3081,25 @@ static void btusb_disconnect(struct usb_interface *intf)
        if (data->isoc)
                usb_set_intfdata(data->isoc, NULL);
 
+       if (data->diag)
+               usb_set_intfdata(data->diag, NULL);
+
        hci_unregister_dev(hdev);
 
-       if (intf == data->isoc)
+       if (intf == data->intf) {
+               if (data->isoc)
+                       usb_driver_release_interface(&btusb_driver, data->isoc);
+               if (data->diag)
+                       usb_driver_release_interface(&btusb_driver, data->diag);
+       } else if (intf == data->isoc) {
+               if (data->diag)
+                       usb_driver_release_interface(&btusb_driver, data->diag);
+               usb_driver_release_interface(&btusb_driver, data->intf);
+       } else if (intf == data->diag) {
                usb_driver_release_interface(&btusb_driver, data->intf);
-       else if (data->isoc)
-               usb_driver_release_interface(&btusb_driver, data->isoc);
+               if (data->isoc)
+                       usb_driver_release_interface(&btusb_driver, data->isoc);
+       }
 
        hci_free_dev(hdev);
 }
@@ -3323,6 +3129,14 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
        btusb_stop_traffic(data);
        usb_kill_anchored_urbs(&data->tx_anchor);
 
+       /* Optionally request a device reset on resume, but only when
+        * wakeups are disabled. If wakeups are enabled we assume the
+        * device will stay powered up throughout suspend.
+        */
+       if (test_bit(BTUSB_RESET_RESUME, &data->flags) &&
+           !device_may_wakeup(&data->udev->dev))
+               data->udev->reset_resume = 1;
+
        return 0;
 }