Bluetooth: btintel: Fix the first HCI command not work with ROM device
authorTedd Ho-Jeong An <tedd.an@intel.com>
Thu, 5 Aug 2021 00:32:12 +0000 (17:32 -0700)
committerMarcel Holtmann <marcel@holtmann.org>
Thu, 5 Aug 2021 14:03:29 +0000 (16:03 +0200)
The some legacy ROM controllers have a bug with the first HCI command
sent to it returning number of completed commands as zero, which would
stall the command processing in the Bluetooth core.

As a workaround, send HCI Rest command first which will reset the
controller to fix the issue.

Signed-off-by: Tedd Ho-Jeong An <tedd.an@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
drivers/bluetooth/btintel.c
drivers/bluetooth/btintel.h
drivers/bluetooth/btusb.c

index a6d75af..8e6b497 100644 (file)
@@ -1676,6 +1676,26 @@ static int btintel_setup_combined(struct hci_dev *hdev)
 
        BT_DBG("%s", hdev->name);
 
+       /* The some controllers have a bug with the first HCI command sent to it
+        * returning number of completed commands as zero. This would stall the
+        * command processing in the Bluetooth core.
+        *
+        * As a workaround, send HCI Reset command first which will reset the
+        * number of completed commands and allow normal command processing
+        * from now on.
+        */
+       if (btintel_test_flag(hdev, INTEL_BROKEN_INITIAL_NCMD)) {
+               skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL,
+                                    HCI_INIT_TIMEOUT);
+               if (IS_ERR(skb)) {
+                       bt_dev_err(hdev,
+                                  "sending initial HCI reset failed (%ld)",
+                                  PTR_ERR(skb));
+                       return PTR_ERR(skb);
+               }
+               kfree_skb(skb);
+       }
+
        /* Starting from TyP device, the command parameter and response are
         * changed even though the OCF for HCI_Intel_Read_Version command
         * remains same. The legacy devices can handle even if the
index fb5e73e..8a49795 100644 (file)
@@ -144,6 +144,7 @@ enum {
        INTEL_FIRMWARE_LOADED,
        INTEL_FIRMWARE_FAILED,
        INTEL_BOOTING,
+       INTEL_BROKEN_INITIAL_NCMD,
 
        __INTEL_NUM_FLAGS,
 };
index 887b883..3ed552d 100644 (file)
@@ -61,6 +61,7 @@ static struct usb_driver btusb_driver;
 #define BTUSB_VALID_LE_STATES   0x800000
 #define BTUSB_QCA_WCN6855      0x1000000
 #define BTUSB_INTEL_NEWGEN     0x2000000
+#define BTUSB_INTEL_BROKEN_INITIAL_NCMD 0x4000000
 
 static const struct usb_device_id btusb_table[] = {
        /* Generic Bluetooth USB device */
@@ -372,7 +373,8 @@ static const struct usb_device_id blacklist_table[] = {
                                                     BTUSB_WIDEBAND_SPEECH |
                                                     BTUSB_VALID_LE_STATES },
        { USB_DEVICE(0x8087, 0x07da), .driver_info = BTUSB_CSR },
-       { USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL_COMBINED },
+       { USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL_COMBINED |
+                                                    BTUSB_INTEL_BROKEN_INITIAL_NCMD },
        { USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL_COMBINED },
        { USB_DEVICE(0x8087, 0x0a2b), .driver_info = BTUSB_INTEL_NEW |
                                                     BTUSB_WIDEBAND_SPEECH },
@@ -4489,6 +4491,9 @@ static int btusb_probe(struct usb_interface *intf,
                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_BROKEN_INITIAL_NCMD)
+                       btintel_set_flag(hdev, INTEL_BROKEN_INITIAL_NCMD);
        }
 
        if (id->driver_info & BTUSB_INTEL_NEW) {