summaryrefslogtreecommitdiff
path: root/drivers/bluetooth/btusb.c
diff options
context:
space:
mode:
authorIsmael Ferreras Morezuelas <swyterzone@gmail.com>2021-07-17 01:21:43 +0200
committerMarcel Holtmann <marcel@holtmann.org>2021-07-29 21:54:42 +0200
commitf4292e2faf522f899b642d2040a2edbcbd455b9f (patch)
tree0f24e9f24bddc6ed8e1fe29a4714bb56abaafad7 /drivers/bluetooth/btusb.c
parentf283f4765b65fde8a1b9927702b107e9fbd06d6a (diff)
Bluetooth: btusb: Make the CSR clone chip force-suspend workaround more generic
Turns out Hans de Goede completed the work I started last year trying to improve Chinese-clone detection of CSR controller chips. Quirk after quirk these Bluetooth dongles are more usable now. Even after a few BlueZ regressions; these clones are so fickle that some days they stop working altogether. Except on Windows, they work fine. But this force-suspend initialization quirk seems to mostly do the trick, after a lot of testing Bluetooth now seems to work *all* the time. The only problem is that the solution ended up being masked under a very stringent check; when there are probably hundreds of fake dongle models out there that benefit from a good reset. Make it so. Fixes: 81cac64ba258a ("Bluetooth: Deal with USB devices that are faking CSR vendor") Fixes: cde1a8a992875 ("Bluetooth: btusb: Fix and detect most of the Chinese Bluetooth controllers") Fixes: d74e0ae7e0303 ("Bluetooth: btusb: Fix detection of some fake CSR controllers with a bcdDevice val of 0x0134") Fixes: 0671c0662383e ("Bluetooth: btusb: Add workaround for remote-wakeup issues with Barrot 8041a02 fake CSR controllers") Cc: stable@vger.kernel.org Cc: Hans de Goede <hdegoede@redhat.com> Tested-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com> Signed-off-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com> Reviewed-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'drivers/bluetooth/btusb.c')
-rw-r--r--drivers/bluetooth/btusb.c55
1 files changed, 30 insertions, 25 deletions
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 07cb5d9dc483..fec798dadd99 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -1900,7 +1900,7 @@ static int btusb_setup_csr(struct hci_dev *hdev)
is_fake = true;
if (is_fake) {
- bt_dev_warn(hdev, "CSR: Unbranded CSR clone detected; adding workarounds...");
+ bt_dev_warn(hdev, "CSR: Unbranded CSR clone detected; adding workarounds and force-suspending once...");
/* Generally these clones have big discrepancies between
* advertised features and what's actually supported.
@@ -1917,41 +1917,46 @@ static int btusb_setup_csr(struct hci_dev *hdev)
clear_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
/*
- * Special workaround for clones with a Barrot 8041a02 chip,
- * these clones are really messed-up:
- * 1. Their bulk rx endpoint will never report any data unless
- * the device was suspended at least once (yes really).
+ * Special workaround for these BT 4.0 chip clones, and potentially more:
+ *
+ * - 0x0134: a Barrot 8041a02 (HCI rev: 0x1012 sub: 0x0810)
+ * - 0x7558: IC markings FR3191AHAL 749H15143 (HCI rev/sub-version: 0x0709)
+ *
+ * These controllers are really messed-up.
+ *
+ * 1. Their bulk RX endpoint will never report any data unless
+ * the device was suspended at least once (yes, really).
* 2. They will not wakeup when autosuspended and receiving data
- * on their bulk rx endpoint from e.g. a keyboard or mouse
+ * on their bulk RX endpoint from e.g. a keyboard or mouse
* (IOW remote-wakeup support is broken for the bulk endpoint).
*
* To fix 1. enable runtime-suspend, force-suspend the
- * hci and then wake-it up by disabling runtime-suspend.
+ * HCI and then wake-it up by disabling runtime-suspend.
*
- * To fix 2. clear the hci's can_wake flag, this way the hci
+ * To fix 2. clear the HCI's can_wake flag, this way the HCI
* will still be autosuspended when it is not open.
+ *
+ * --
+ *
+ * Because these are widespread problems we prefer generic solutions; so
+ * apply this initialization quirk to every controller that gets here,
+ * it should be harmless. The alternative is to not work at all.
*/
- if (bcdDevice == 0x8891 &&
- le16_to_cpu(rp->lmp_subver) == 0x1012 &&
- le16_to_cpu(rp->hci_rev) == 0x0810 &&
- le16_to_cpu(rp->hci_ver) == BLUETOOTH_VER_4_0) {
- bt_dev_warn(hdev, "CSR: detected a fake CSR dongle using a Barrot 8041a02 chip, this chip is very buggy and may have issues");
+ pm_runtime_allow(&data->udev->dev);
- pm_runtime_allow(&data->udev->dev);
+ ret = pm_runtime_suspend(&data->udev->dev);
+ if (ret >= 0)
+ msleep(200);
+ else
+ bt_dev_err(hdev, "CSR: Failed to suspend the device for our Barrot 8041a02 receive-issue workaround");
- ret = pm_runtime_suspend(&data->udev->dev);
- if (ret >= 0)
- msleep(200);
- else
- bt_dev_err(hdev, "Failed to suspend the device for Barrot 8041a02 receive-issue workaround");
+ pm_runtime_forbid(&data->udev->dev);
- pm_runtime_forbid(&data->udev->dev);
+ device_set_wakeup_capable(&data->udev->dev, false);
- device_set_wakeup_capable(&data->udev->dev, false);
- /* Re-enable autosuspend if this was requested */
- if (enable_autosuspend)
- usb_enable_autosuspend(data->udev);
- }
+ /* Re-enable autosuspend if this was requested */
+ if (enable_autosuspend)
+ usb_enable_autosuspend(data->udev);
}
kfree_skb(skb);