Message ID | 20221004163224.1.I46e98b47be875d0b9abff2d19417c612077d1909@changeid |
---|---|
State | New |
Headers | show |
Series | Bluetooth: btusb: Introduce generic USB reset | expand |
Hi Archie, On Tue, Oct 4, 2022 at 1:33 AM Archie Pusaka <apusaka@google.com> wrote: > > From: Archie Pusaka <apusaka@chromium.org> > > On cmd_timeout and there is no reset_gpio, reset the USB port as a > last resort. > > Signed-off-by: Archie Pusaka <apusaka@chromium.org> > Reviewed-by: Abhishek Pandit-Subedi <abhishekpandit@google.com> > Reviewed-by: Ying Hsu <yinghsu@chromium.org> > > --- > > 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 >
Hi Luiz, On Wed, 5 Oct 2022 at 04:53, Luiz Augusto von Dentz <luiz.dentz@gmail.com> wrote: > > Hi Archie, > > On Tue, Oct 4, 2022 at 1:33 AM Archie Pusaka <apusaka@google.com> wrote: > > > > From: Archie Pusaka <apusaka@chromium.org> > > > > On cmd_timeout and there is no reset_gpio, reset the USB port as a > > last resort. > > > > Signed-off-by: Archie Pusaka <apusaka@chromium.org> > > Reviewed-by: Abhishek Pandit-Subedi <abhishekpandit@google.com> > > Reviewed-by: Ying Hsu <yinghsu@chromium.org> > > > > --- > > > > 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); > OK, will update > > +} > > + > > 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? OK. I think this is safe at least for now, since resetting btusb is probably better than just giving up doing nothing. But I can add hdev->reset if that is desirable. > 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. > I am not familiar with this part. Perhaps it's better for this to be managed by another patch, since it is not the focus of this patch? > > 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 Cheers, Archie
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); +} + 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); 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)