Thread (2 messages) read the whole thread 2 messages, 2 authors, 2020-06-24

Re: [PATCH] Bluetooth: btusb: Reset port on cmd timeout

From: Marcel Holtmann <marcel@holtmann.org>
Date: 2020-06-24 18:02:07
Also in: linux-pm, linux-usb, lkml

Hi Abhishek,
quoted hunk ↗ jump to hunk
QCA_ROME doesn't have support for the reset gpio but sometimes gets into
a state where it is unresponsive to commands. When this happens, reset
the port to attempt to revive the chip.

Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org>
---
On Chromebooks with this chipset, we encountered cmd_timeout after
running suspend stress test for hundreds of iterations. Without
a recovery mechanism, continued cmd_timeout failures eventually caused
the suspend stress test to fail.

This change will just reset the port that the Bluetooth chip is on when
cmd_timeout is encountered. At the very least, the driver will unload
and stop affecting suspend. It doesn't seem to restore the BT controller
to a good state however (this still requires a power cycle).

drivers/bluetooth/btusb.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index e42fdd625eb023..b806a88702328b 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -573,6 +573,22 @@ static void btusb_rtl_cmd_timeout(struct hci_dev *hdev)
	gpiod_set_value_cansleep(reset_gpio, 0);
}

+static void btusb_generic_usb_cmd_timeout(struct hci_dev *hdev)
+{
+	struct btusb_data *data = hci_get_drvdata(hdev);
+	int err;
+
+	if (++data->cmd_timeout_cnt < 5)
+		return;
+
+	bt_dev_err(hdev, "Multiple cmd timeouts seen. Resetting usb device.");
+	err = usb_autopm_get_interface(data->intf);
+	if (!err)
+		usb_queue_reset_device(data->intf);
+	else
+		bt_dev_err(hdev, "Failed usb_autopm_get_interface with %d", err);
+}
+
static inline void btusb_free_frags(struct btusb_data *data)
{
	unsigned long flags;
@@ -3964,6 +3980,7 @@ 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;
+		hdev->cmd_timeout = btusb_generic_usb_cmd_timeout;
lets give this a btusb_qca_cmd_timeout name. If it ever gets generic, we can rename it, but right now it is specific to QCA.

Regards

Marcel
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help