[PATCH v3 2/2] Bluetooth: btusb: Fix leaked runtime PM reference in btusb_reset
Jiajia Liu
liujiajia at kylinos.cn
Thu Aug 20 23:26:06 PDT 2026
btusb_reset calls usb_autopm_get_interface to resume the device
before queuing a reset of it, but never calls the matching
usb_autopm_put_interface.
usb_queue_reset_device ends up in usb_reset_device(), and since
btusb provides no pre_reset/post_reset callbacks the interface is
merely unbound and rebound: the interface device object survives
this cycle, and so does its PM usage count, which is not cleared
when the driver is unbound.
As a result every reset permanently leaks a PM usage reference,
preventing the interface from being runtime suspended again until
it is unbound.
Set BTUSB_RESET flag after usb_autopm_get_interface so that
btusb_disconnect drops the reference. If the flag is already set,
drop the newly acquired reference and return.
Fixes: c9209b269afd ("Bluetooth: btusb: Introduce generic USB reset")
Assisted-by: Claude:qwen3.8-max
Signed-off-by: Jiajia Liu <liujiajia at kylinos.cn>
---
Changes in v3:
- handle multiple reset requests int btusb_reset (sashiko)
set BTUSB_RESET after usb_autopm_get_interface. If the flag is
already set, drop newly acquired reference and return.
- drop the comment
Changes in v2:
- Fix the race window (sashiko)
set BTUSB_USB_RESET_ACTIVE flag before usb_queue_reset_device.
Changes in v1:
- add usb_autopm_put_interface after usb_queue_reset_device
---
drivers/bluetooth/btusb.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 360cec460ce7..37946cff6156 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -1033,13 +1033,18 @@ static void btusb_reset(struct hci_dev *hdev)
int err;
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;
}
+ if (test_and_set_bit(BTUSB_RESET, &data->flags)) {
+ bt_dev_err(hdev, "last usb reset failed? Not resetting again");
+ usb_autopm_put_interface_no_suspend(data->intf);
+ return;
+ }
+
bt_dev_err(hdev, "Resetting usb device.");
usb_queue_reset_device(data->intf);
}
--
2.55.0
More information about the Linux-mediatek
mailing list