Commit 2250abad authored by Benjamin Berg's avatar Benjamin Berg Committed by Luiz Augusto von Dentz

Bluetooth: hci_core: Cancel sync command if sending a frame failed

If sending a frame failed any sync command associated with it will never
be completed. As such, cancel any such command immediately to avoid
timing out.
Signed-off-by: default avatarBenjamin Berg <bberg@redhat.com>
Signed-off-by: default avatarLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
parent 914b08b3
...@@ -2906,7 +2906,7 @@ int hci_unregister_cb(struct hci_cb *cb) ...@@ -2906,7 +2906,7 @@ int hci_unregister_cb(struct hci_cb *cb)
} }
EXPORT_SYMBOL(hci_unregister_cb); EXPORT_SYMBOL(hci_unregister_cb);
static void hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) static int hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
{ {
int err; int err;
...@@ -2929,14 +2929,17 @@ static void hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -2929,14 +2929,17 @@ static void hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
if (!test_bit(HCI_RUNNING, &hdev->flags)) { if (!test_bit(HCI_RUNNING, &hdev->flags)) {
kfree_skb(skb); kfree_skb(skb);
return; return -EINVAL;
} }
err = hdev->send(hdev, skb); err = hdev->send(hdev, skb);
if (err < 0) { if (err < 0) {
bt_dev_err(hdev, "sending frame failed (%d)", err); bt_dev_err(hdev, "sending frame failed (%d)", err);
kfree_skb(skb); kfree_skb(skb);
return err;
} }
return 0;
} }
/* Send HCI command */ /* Send HCI command */
...@@ -3843,10 +3846,15 @@ static void hci_cmd_work(struct work_struct *work) ...@@ -3843,10 +3846,15 @@ static void hci_cmd_work(struct work_struct *work)
hdev->sent_cmd = skb_clone(skb, GFP_KERNEL); hdev->sent_cmd = skb_clone(skb, GFP_KERNEL);
if (hdev->sent_cmd) { if (hdev->sent_cmd) {
int res;
if (hci_req_status_pend(hdev)) if (hci_req_status_pend(hdev))
hci_dev_set_flag(hdev, HCI_CMD_PENDING); hci_dev_set_flag(hdev, HCI_CMD_PENDING);
atomic_dec(&hdev->cmd_cnt); atomic_dec(&hdev->cmd_cnt);
hci_send_frame(hdev, skb);
res = hci_send_frame(hdev, skb);
if (res < 0)
hci_cmd_sync_cancel(hdev, -res);
if (test_bit(HCI_RESET, &hdev->flags)) if (test_bit(HCI_RESET, &hdev->flags))
cancel_delayed_work(&hdev->cmd_timer); cancel_delayed_work(&hdev->cmd_timer);
else else
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment