summaryrefslogtreecommitdiff
path: root/drivers/bluetooth/btusb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/bluetooth/btusb.c')
-rw-r--r--drivers/bluetooth/btusb.c40
1 files changed, 25 insertions, 15 deletions
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 56c6ca7905ff..9944169f2a22 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -2569,7 +2569,8 @@ static void btusb_mtk_wmt_recv(struct urb *urb)
skb = bt_skb_alloc(HCI_WMT_MAX_EVENT_SIZE, GFP_ATOMIC);
if (!skb) {
hdev->stat.err_rx++;
- goto err_out;
+ kfree(urb->setup_packet);
+ return;
}
hci_skb_pkt_type(skb) = HCI_EVENT_PKT;
@@ -2587,13 +2588,20 @@ static void btusb_mtk_wmt_recv(struct urb *urb)
*/
if (test_bit(BTUSB_TX_WAIT_VND_EVT, &data->flags)) {
data->evt_skb = skb_clone(skb, GFP_ATOMIC);
- if (!data->evt_skb)
- goto err_out;
+ if (!data->evt_skb) {
+ kfree_skb(skb);
+ kfree(urb->setup_packet);
+ return;
+ }
}
err = hci_recv_frame(hdev, skb);
- if (err < 0)
- goto err_free_skb;
+ if (err < 0) {
+ kfree_skb(data->evt_skb);
+ data->evt_skb = NULL;
+ kfree(urb->setup_packet);
+ return;
+ }
if (test_and_clear_bit(BTUSB_TX_WAIT_VND_EVT,
&data->flags)) {
@@ -2602,11 +2610,7 @@ static void btusb_mtk_wmt_recv(struct urb *urb)
wake_up_bit(&data->flags,
BTUSB_TX_WAIT_VND_EVT);
}
-err_out:
- return;
-err_free_skb:
- kfree_skb(data->evt_skb);
- data->evt_skb = NULL;
+ kfree(urb->setup_packet);
return;
} else if (urb->status == -ENOENT) {
/* Avoid suspend failed when usb_kill_urb */
@@ -2627,6 +2631,7 @@ err_free_skb:
usb_anchor_urb(urb, &data->ctrl_anchor);
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err < 0) {
+ kfree(urb->setup_packet);
/* -EPERM: urb is being killed;
* -ENODEV: device got disconnected
*/
@@ -2701,11 +2706,6 @@ static int btusb_mtk_hci_wmt_sync(struct hci_dev *hdev,
struct btmtk_wmt_hdr *hdr;
int err;
- /* Submit control IN URB on demand to process the WMT event */
- err = btusb_mtk_submit_wmt_recv_urb(hdev);
- if (err < 0)
- return err;
-
/* Send the WMT command and wait until the WMT event returns */
hlen = sizeof(*hdr) + wmt_params->dlen;
if (hlen > 255)
@@ -2727,6 +2727,11 @@ static int btusb_mtk_hci_wmt_sync(struct hci_dev *hdev,
return err;
}
+ /* Submit control IN URB on demand to process the WMT event */
+ err = btusb_mtk_submit_wmt_recv_urb(hdev);
+ if (err < 0)
+ return err;
+
/* The vendor specific WMT commands are all answered by a vendor
* specific event and will have the Command Status or Command
* Complete as with usual HCI command flow control.
@@ -3264,6 +3269,11 @@ static int btusb_setup_qca_download_fw(struct hci_dev *hdev,
sent += size;
count -= size;
+ /* ep2 need time to switch from function acl to function dfu,
+ * so we add 20ms delay here.
+ */
+ msleep(20);
+
while (count) {
size = min_t(size_t, count, QCA_DFU_PACKET_LEN);