Created
June 29, 2020 19:40
-
-
Save Vudentz/464fb0065a73e5c99bdb66cd2c5a1a2d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h | |
index d4e28773d378..7bd74d7a07db 100644 | |
--- a/include/net/bluetooth/hci_core.h | |
+++ b/include/net/bluetooth/hci_core.h | |
@@ -400,6 +400,7 @@ struct hci_dev { | |
struct delayed_work le_scan_restart; | |
struct sk_buff_head rx_q; | |
+ struct sk_buff_head ev_q; | |
struct sk_buff_head raw_q; | |
struct sk_buff_head cmd_q; | |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c | |
index 2e7bc2da8371..09945ccbdf3a 100644 | |
--- a/net/bluetooth/hci_core.c | |
+++ b/net/bluetooth/hci_core.c | |
@@ -1589,6 +1589,7 @@ static int hci_dev_do_open(struct hci_dev *hdev) | |
skb_queue_purge(&hdev->cmd_q); | |
skb_queue_purge(&hdev->rx_q); | |
+ skb_queue_purge(&hdev->ev_q); | |
if (hdev->flush) | |
hdev->flush(hdev); | |
@@ -1776,6 +1777,7 @@ int hci_dev_do_close(struct hci_dev *hdev) | |
/* Drop queues */ | |
skb_queue_purge(&hdev->rx_q); | |
+ skb_queue_purge(&hdev->ev_q); | |
skb_queue_purge(&hdev->cmd_q); | |
skb_queue_purge(&hdev->raw_q); | |
@@ -1847,6 +1849,7 @@ static int hci_dev_do_reset(struct hci_dev *hdev) | |
/* Drop queues */ | |
skb_queue_purge(&hdev->rx_q); | |
+ skb_queue_purge(&hdev->ev_q); | |
skb_queue_purge(&hdev->cmd_q); | |
/* Avoid potential lockdep warnings from the *_flush() calls by | |
@@ -3440,6 +3443,7 @@ struct hci_dev *hci_alloc_dev(void) | |
INIT_DELAYED_WORK(&hdev->power_off, hci_power_off); | |
skb_queue_head_init(&hdev->rx_q); | |
+ skb_queue_head_init(&hdev->ev_q); | |
skb_queue_head_init(&hdev->cmd_q); | |
skb_queue_head_init(&hdev->raw_q); | |
@@ -3703,7 +3707,18 @@ int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb) | |
/* Time stamp */ | |
__net_timestamp(skb); | |
- skb_queue_tail(&hdev->rx_q, skb); | |
+ switch (hci_skb_pkt_type(skb)) { | |
+ case HCI_EVENT_PKT: | |
+ /* Event packets are queue separately so they be processed | |
+ * first. | |
+ */ | |
+ skb_queue_tail(&hdev->ev_q, skb); | |
+ break; | |
+ default: | |
+ skb_queue_tail(&hdev->rx_q, skb); | |
+ break' | |
+ } | |
+ | |
queue_work(hdev->workqueue, &hdev->rx_work); | |
return 0; | |
@@ -4640,14 +4655,11 @@ void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status, | |
spin_unlock_irqrestore(&hdev->cmd_q.lock, flags); | |
} | |
-static void hci_rx_work(struct work_struct *work) | |
+static void hci_dequeue(struct hci_dev *dev, struct sk_buff_head *queue) | |
{ | |
- struct hci_dev *hdev = container_of(work, struct hci_dev, rx_work); | |
struct sk_buff *skb; | |
- BT_DBG("%s", hdev->name); | |
- | |
- while ((skb = skb_dequeue(&hdev->rx_q))) { | |
+ while ((skb = skb_dequeue(queue))) { | |
/* Send copy to monitor */ | |
hci_send_to_monitor(hdev, skb); | |
@@ -4703,6 +4715,17 @@ static void hci_rx_work(struct work_struct *work) | |
} | |
} | |
+static void hci_rx_work(struct work_struct *work) | |
+{ | |
+ struct hci_dev *hdev = container_of(work, struct hci_dev, rx_work); | |
+ | |
+ BT_DBG("%s", hdev->name); | |
+ | |
+ /* Process HCI event packets so states changes are synchronized */ | |
+ hci_dequeue(hdev, &hdev->ev_q); | |
+ hci_dequeue(hdev, &hdev->rx_q); | |
+} | |
+ | |
static void hci_cmd_work(struct work_struct *work) | |
{ | |
struct hci_dev *hdev = container_of(work, struct hci_dev, cmd_work); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment