[PATCH v5 2/2] Bluetooth: btusb: Fix leaked runtime PM reference in btusb_reset
Ying Hsu
yinghsu at chromium.org
Wed Sep 23 02:53:49 PDT 2026
Another way to address this would be to let the USB core handle the PM
bookkeeping instead of doing it in btusb.
On Fri, Sep 4, 2026 at 4:04 PM Jiajia Liu <liujiajia at kylinos.cn> wrote:
>
> 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 before usb_queue_reset_device so that
> btusb_disconnect drops the reference. If the flag is already set,
> drop one reference.
>
> 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 v5:
> - no change
>
> Changes in v4:
> - do not return if BTUSB_RESET is set in case the first reset failed.
> (sashiko)
>
> 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.
>
> 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 | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
> index 6f7946709266..61c18402911a 100644
> --- a/drivers/bluetooth/btusb.c
> +++ b/drivers/bluetooth/btusb.c
> @@ -1068,13 +1068,15 @@ 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))
> + usb_autopm_put_interface_no_suspend(data->intf);
> +
> bt_dev_err(hdev, "Resetting usb device.");
> usb_queue_reset_device(data->intf);
> }
> --
> 2.55.0
>
More information about the linux-arm-kernel
mailing list