Commit c9209b26 authored by Archie Pusaka's avatar Archie Pusaka Committed by Luiz Augusto von Dentz

Bluetooth: btusb: Introduce generic USB reset

On cmd_timeout with no reset_gpio, reset the USB port as a last
resort.

This patch changes the behavior of btusb_intel_cmd_timeout and
btusb_rtl_cmd_timeout.
Signed-off-by: default avatarArchie Pusaka <apusaka@chromium.org>
Reviewed-by: default avatarAbhishek Pandit-Subedi <abhishekpandit@google.com>
Reviewed-by: default avatarYing Hsu <yinghsu@chromium.org>
Signed-off-by: default avatarLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
parent f9c5cbd5
......@@ -696,6 +696,28 @@ struct btusb_data {
unsigned cmd_timeout_cnt;
};
static void btusb_reset(struct hci_dev *hdev)
{
struct btusb_data *data;
int err;
if (hdev->reset) {
hdev->reset(hdev);
return;
}
data = hci_get_drvdata(hdev);
/* This is not an unbalanced PM reference since the device will reset */
err = usb_autopm_get_interface(data->intf);
if (err) {
bt_dev_err(hdev, "Failed usb_autopm_get_interface: %d", err);
return;
}
bt_dev_err(hdev, "Resetting usb device.");
usb_queue_reset_device(data->intf);
}
static void btusb_intel_cmd_timeout(struct hci_dev *hdev)
{
struct btusb_data *data = hci_get_drvdata(hdev);
......@@ -705,7 +727,7 @@ static void btusb_intel_cmd_timeout(struct hci_dev *hdev)
return;
if (!reset_gpio) {
bt_dev_err(hdev, "No way to reset. Ignoring and continuing");
btusb_reset(hdev);
return;
}
......@@ -736,7 +758,7 @@ static void btusb_rtl_cmd_timeout(struct hci_dev *hdev)
return;
if (!reset_gpio) {
bt_dev_err(hdev, "No gpio to reset Realtek device, ignoring");
btusb_reset(hdev);
return;
}
......@@ -761,7 +783,6 @@ static void btusb_qca_cmd_timeout(struct hci_dev *hdev)
{
struct btusb_data *data = hci_get_drvdata(hdev);
struct gpio_desc *reset_gpio = data->reset_gpio;
int err;
if (++data->cmd_timeout_cnt < 5)
return;
......@@ -787,13 +808,7 @@ static void btusb_qca_cmd_timeout(struct hci_dev *hdev)
return;
}
bt_dev_err(hdev, "Multiple cmd timeouts seen. Resetting usb device.");
/* This is not an unbalanced PM reference since the device will reset */
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);
btusb_reset(hdev);
}
static inline void btusb_free_frags(struct btusb_data *data)
......
......@@ -659,6 +659,7 @@ struct hci_dev {
int (*set_diag)(struct hci_dev *hdev, bool enable);
int (*set_bdaddr)(struct hci_dev *hdev, const bdaddr_t *bdaddr);
void (*cmd_timeout)(struct hci_dev *hdev);
void (*reset)(struct hci_dev *hdev);
bool (*wakeup)(struct hci_dev *hdev);
int (*set_quality_report)(struct hci_dev *hdev, bool enable);
int (*get_data_path_id)(struct hci_dev *hdev, __u8 *data_path);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment