Hi Archie, On Tue, Oct 4, 2022 at 1:33 AM Archie Pusaka <apusaka@xxxxxxxxxx> wrote: > > From: Archie Pusaka <apusaka@xxxxxxxxxxxx> > > On cmd_timeout and there is no reset_gpio, reset the USB port as a > last resort. > > Signed-off-by: Archie Pusaka <apusaka@xxxxxxxxxxxx> > Reviewed-by: Abhishek Pandit-Subedi <abhishekpandit@xxxxxxxxxx> > Reviewed-by: Ying Hsu <yinghsu@xxxxxxxxxxxx> > > --- > > drivers/bluetooth/btusb.c | 26 ++++++++++++++++---------- > 1 file changed, 16 insertions(+), 10 deletions(-) > > diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c > index 271963805a38..11040124ef79 100644 > --- a/drivers/bluetooth/btusb.c > +++ b/drivers/bluetooth/btusb.c > @@ -696,6 +696,19 @@ struct btusb_data { > unsigned cmd_timeout_cnt; > }; > > +static void generic_usb_reset(struct hci_dev *hdev, struct btusb_data *data) > +{ > + int err; > + > + bt_dev_err(hdev, "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: %d", err); Lets just have one line printed if it fails: 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 +718,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"); > + generic_usb_reset(hdev, data); Lets call it btusb_reset since this is specific for the data->intf, btw is this safe, or perhaps we want to refactor this to have it callback based so each vendor can add it own specific hdev->reset callback hardware reset with btusb_reset serving as default callback? Also the logic of btusb_intel_cmd_timeout should probably be put inside btintel.c and I don't think we need the gpio_desc reference to be inside the btusb_data since we can call gpiod_get_optional during the reset phase and immediately do gpiod_put after done using it. > return; > } > > @@ -736,7 +749,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"); > + generic_usb_reset(hdev, data); > return; > } > > @@ -761,7 +774,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 +799,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); > + generic_usb_reset(hdev, data); > } > > static inline void btusb_free_frags(struct btusb_data *data) > -- > 2.38.0.rc1.362.ged0d419d3c-goog > -- Luiz Augusto von Dentz