aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bluetooth
diff options
context:
space:
mode:
authorBenjamin Berg <bberg@redhat.com>2021-12-03 15:59:02 +0100
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2021-12-03 10:41:59 -0800
commitc97a747efc93f94a4ad6c707972dfbf8d774edf9 (patch)
tree9b720088b82a16bfcabb17ed8bb529091f7e1ba8 /drivers/bluetooth
parentBluetooth: hci_core: Cancel sync command if sending a frame failed (diff)
downloadlinux-dev-c97a747efc93f94a4ad6c707972dfbf8d774edf9.tar.xz
linux-dev-c97a747efc93f94a4ad6c707972dfbf8d774edf9.zip
Bluetooth: btusb: Cancel sync commands for certain URB errors
Cancel sync commands when transmission of URBs fail. This is done for both failures to send a command URB and also when the interrupt URB used to retrieve a response fails. This approach is sufficient to quickly deal with certain errors such as a device being disconnected while synchronous commands are done during initialization. Signed-off-by: Benjamin Berg <bberg@redhat.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Diffstat (limited to 'drivers/bluetooth')
-rw-r--r--drivers/bluetooth/btusb.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index ab169fc673ea..d9067a8fad60 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -933,6 +933,8 @@ static void btusb_intr_complete(struct urb *urb)
if (err != -EPERM && err != -ENODEV)
bt_dev_err(hdev, "urb %p failed to resubmit (%d)",
urb, -err);
+ if (err != -EPERM)
+ hci_cmd_sync_cancel(hdev, -err);
usb_unanchor_urb(urb);
}
}
@@ -976,6 +978,8 @@ static int btusb_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags)
if (err != -EPERM && err != -ENODEV)
bt_dev_err(hdev, "urb %p submission failed (%d)",
urb, -err);
+ if (err != -EPERM)
+ hci_cmd_sync_cancel(hdev, -err);
usb_unanchor_urb(urb);
}
@@ -1331,10 +1335,13 @@ static void btusb_tx_complete(struct urb *urb)
if (!test_bit(HCI_RUNNING, &hdev->flags))
goto done;
- if (!urb->status)
+ if (!urb->status) {
hdev->stat.byte_tx += urb->transfer_buffer_length;
- else
+ } else {
+ if (hci_skb_pkt_type(skb) == HCI_COMMAND_PKT)
+ hci_cmd_sync_cancel(hdev, -urb->status);
hdev->stat.err_tx++;
+ }
done:
spin_lock_irqsave(&data->txlock, flags);