diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 3418d7b964a1..187dda1e5950 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1466,7 +1466,7 @@ static void hci_cmd_timeout(struct work_struct *work) if (hdev->req_skb) { u16 opcode = hci_skb_opcode(hdev->req_skb); - bt_dev_err(hdev, "command 0x%4.4x tx timeout", opcode); + bt_dev_err(hdev, "command 0x%4.4x skb: %p tx timeout hdev: %p", opcode, hdev->req_skb, hdev); hci_cmd_sync_cancel_sync(hdev, ETIMEDOUT); } else { @@ -4138,6 +4138,7 @@ static void hci_send_cmd_sync(struct hci_dev *hdev, struct sk_buff *skb) if (hci_skb_opcode(skb) != HCI_OP_NOP) { err = hci_send_frame(hdev, skb); + printk("err: %d, skb: %p, %s\n", err, skb, __func__); if (err < 0) { hci_cmd_sync_cancel_sync(hdev, -err); return; @@ -4163,6 +4164,7 @@ static void hci_cmd_work(struct work_struct *work) /* Send queued commands */ if (atomic_read(&hdev->cmd_cnt)) { skb = skb_dequeue(&hdev->cmd_q); + printk("dequeue skb:%p, hdev: %p, %s\n", skb, hdev, __func__); if (!skb) return; diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c index 6e76798ec786..4bf39cd402be 100644 --- a/net/bluetooth/hci_sync.c +++ b/net/bluetooth/hci_sync.c @@ -158,8 +158,9 @@ struct sk_buff *__hci_cmd_sync_sk(struct hci_dev *hdev, u16 opcode, u32 plen, struct sock *sk) { struct hci_request req; - struct sk_buff *skb; + struct sk_buff *skb, *new_skb; int err = 0; + unsigned long flags; bt_dev_dbg(hdev, "Opcode 0x%4.4x", opcode); @@ -169,6 +170,7 @@ struct sk_buff *__hci_cmd_sync_sk(struct hci_dev *hdev, u16 opcode, u32 plen, hdev->req_status = HCI_REQ_PEND; + new_skb = skb_peek_tail(&req.cmd_q); err = hci_req_sync_run(&req); if (err < 0) return ERR_PTR(err); @@ -203,16 +205,33 @@ struct sk_buff *__hci_cmd_sync_sk(struct hci_dev *hdev, u16 opcode, u32 plen, if (err < 0) { kfree_skb(skb); - return ERR_PTR(err); + goto out; } /* If command return a status event skb will be set to NULL as there are * no parameters. */ - if (!skb) - return ERR_PTR(-ENODATA); + if (!skb) { + err = -ENODATA; + goto out; + } return skb; + +out: + if (!skb_queue_empty(&hdev->cmd_q)) { + spin_lock_irqsave(&hdev->cmd_q.lock, flags); + skb = __skb_dequeue_tail(&hdev->cmd_q); + spin_unlock_irqrestore(&hdev->cmd_q.lock, flags); + } else { + printk("!!!!!!!!! skb: %p, nskb: %p, %s\n", skb, new_skb, __func__); + skb = new_skb; + } + + printk(">>>>> remove skb: %p, tskb: %p, hdev: %p, %s\n", skb, new_skb, hdev, __func__); + kfree_skb(skb); + + return ERR_PTR(err); } EXPORT_SYMBOL(__hci_cmd_sync_sk);