diff options
| author | Jiajia Liu <liujiajia@kylinos.cn> | 2026-09-04 16:03:50 +0800 |
|---|---|---|
| committer | Luiz Augusto von Dentz <luiz.von.dentz@intel.com> | 2026-09-08 17:15:39 -0400 |
| commit | e486a891c412d9d82ee865987f4eead6196e1f96 (patch) | |
| tree | 7bc8cb489457a8bf4ae7df3f7fca0efb2c1f83a4 | |
| parent | f5a427b16e45210dee656b0860728f3d496dee85 (diff) | |
| download | linux-next-e486a891c412d9d82ee865987f4eead6196e1f96.tar.gz linux-next-e486a891c412d9d82ee865987f4eead6196e1f96.zip | |
Bluetooth: btusb: mediatek: Fix leaked runtime PM reference in reset
MT7925 on HP Pro Mini 260 sometimes timed out during reloading driver
and reset usb device. btusb_suspend is not called again after closing
bluetooth interface.
usbcore: registered new interface driver btusb
Bluetooth: hci0: HW/SW Version: 0x00000000, Build Time: 20260605184935
Bluetooth: hci0: Execution of wmt command timed out
Bluetooth: hci0: Failed to send wmt patch dwnld (-110)
Bluetooth: hci0: Failed to set up firmware (-110)
usb 3-10: reset high-speed USB device number 4 using xhci_hcd
Bluetooth: hci0: HW/SW Version: 0x00000000, Build Time: 20260605184935
Bluetooth: hci0: Device setup in 1856545 usecs
Bluetooth: hci0: AOSP extensions version v1.00
Bluetooth: hci0: AOSP quality report is supported
Bluetooth: MGMT ver 1.23
btusb_mtk_reset calls usb_autopm_get_interface to resume the device
before driving the hardware reset, but never calls the matching
usb_autopm_put_interface. Every hardware reset therefore leaks a PM
usage reference of the interface, preventing the device from being
runtime suspended again until it is unbound.
Add the BTUSB_RESET flag. It is set before usb_queue_reset_device
and is cleared in btusb_disconnect, which drops the reference as well.
If the flag is already set when a new reset is requested, drop one
reference.
Also clear BTMTK_HW_RESET_ACTIVE if usb_autopm_get_interface fails,
otherwise no further reset could ever be attempted.
Fixes: 25b6d7593a3a ("Bluetooth: btmtk: introduce btmtk reset work")
Assisted-by: Claude:qwen3.8-max
Signed-off-by: Jiajia Liu <liujiajia@kylinos.cn>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
| -rw-r--r-- | drivers/bluetooth/btusb.c | 14 |
1 files changed, 13 insertions, 1 deletions
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index ddc44ca28722..9372fb521575 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -982,6 +982,7 @@ struct btqca_data { #define BTUSB_ALT6_CONTINUOUS_TX 16 #define BTUSB_HW_SSR_ACTIVE 17 #define BTUSB_WAKEUP_BROKEN 18 +#define BTUSB_RESET 19 struct btusb_data { struct hci_dev *hdev; @@ -2931,8 +2932,11 @@ static int btusb_mtk_reset(struct hci_dev *hdev, void *rst_data) } err = usb_autopm_get_interface(data->intf); - if (err < 0) + if (err < 0) { + bt_dev_err(hdev, "Failed usb_autopm_get_interface: %d", err); + clear_bit(BTMTK_HW_RESET_ACTIVE, &btmtk_data->flags); return err; + } /* Release MediaTek ISO data interface */ btusb_mtk_release_iso_intf(hdev); @@ -2954,6 +2958,11 @@ static int btusb_mtk_reset(struct hci_dev *hdev, void *rst_data) err = btmtk_usb_subsys_reset(hdev, btmtk_data->dev_id); + if (test_and_set_bit(BTUSB_RESET, &data->flags)) { + bt_dev_err(hdev, "last usb reset failed? Resetting again"); + usb_autopm_put_interface_no_suspend(data->intf); + } + usb_queue_reset_device(data->intf); clear_bit(BTMTK_HW_RESET_ACTIVE, &btmtk_data->flags); @@ -4596,6 +4605,9 @@ static void btusb_disconnect(struct usb_interface *intf) if (data->reset_gpio) gpiod_put(data->reset_gpio); + if (test_and_clear_bit(BTUSB_RESET, &data->flags)) + usb_autopm_put_interface_no_suspend(data->intf); + if (intf == data->intf) { if (data->isoc) usb_driver_release_interface(&btusb_driver, data->isoc); |
