Bluetooth: handle priority change within quote
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Wed, 2 Nov 2011 13:52:02 +0000 (15:52 +0200)
committerGustavo F. Padovan <padovan@profusion.mobi>
Mon, 7 Nov 2011 19:24:56 +0000 (17:24 -0200)
The quote is calculated based on the first buffer in the queue so if the
priority changes to something lower than the priority of the first skb
the quote needs to be recalculated.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
net/bluetooth/hci_core.c

index 631327dc7fed3caf76fd5d1bb5c8c5b48519d086..19e44533fb01223466c20449a5b89754c9526036 100644 (file)
@@ -2193,10 +2193,17 @@ static inline void hci_sched_acl(struct hci_dev *hdev)
 
        while (hdev->acl_cnt &&
                        (chan = hci_chan_sent(hdev, ACL_LINK, &quote))) {
-               while (quote-- && (skb = skb_dequeue(&chan->data_q))) {
+               u32 priority = (skb_peek(&chan->data_q))->priority;
+               while (quote-- && (skb = skb_peek(&chan->data_q))) {
                        BT_DBG("chan %p skb %p len %d priority %u", chan, skb,
                                        skb->len, skb->priority);
 
+                       /* Stop if priority has changed */
+                       if (skb->priority < priority)
+                               break;
+
+                       skb = skb_dequeue(&chan->data_q);
+
                        hci_conn_enter_active_mode(chan->conn,
                                                bt_cb(skb)->force_active);
 
@@ -2278,10 +2285,17 @@ static inline void hci_sched_le(struct hci_dev *hdev)
 
        cnt = hdev->le_pkts ? hdev->le_cnt : hdev->acl_cnt;
        while (cnt && (chan = hci_chan_sent(hdev, LE_LINK, &quote))) {
-               while (quote-- && (skb = skb_dequeue(&chan->data_q))) {
+               u32 priority = (skb_peek(&chan->data_q))->priority;
+               while (quote-- && (skb = skb_peek(&chan->data_q))) {
                        BT_DBG("chan %p skb %p len %d priority %u", chan, skb,
                                        skb->len, skb->priority);
 
+                       /* Stop if priority has changed */
+                       if (skb->priority < priority)
+                               break;
+
+                       skb = skb_dequeue(&chan->data_q);
+
                        hci_send_frame(skb);
                        hdev->le_last_tx = jiffies;