Bluetooth: Reassemble all available data when retransmissions succeed.
authorMat Martineau <mathewm@codeaurora.org>
Fri, 18 May 2012 03:53:45 +0000 (20:53 -0700)
committerJohan Hedberg <johan.hedberg@intel.com>
Tue, 5 Jun 2012 03:34:04 +0000 (06:34 +0300)
As retransmitted packets arrive, attempt to reassemble SDUs.  If all
requested retransmissions have been received, acknowledge them and
transition back to the RECV state.

Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
net/bluetooth/l2cap_core.c

index 5823697cf9def621580d4e9fe73969247fef53bb..fd324d4cb21722cf29c7a47465cc02fd690b9181 100644 (file)
@@ -4504,8 +4504,36 @@ void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
 
 static int l2cap_rx_queued_iframes(struct l2cap_chan *chan)
 {
-       /* Placeholder */
-       return 0;
+       int err = 0;
+       /* Pass sequential frames to l2cap_reassemble_sdu()
+        * until a gap is encountered.
+        */
+
+       BT_DBG("chan %p", chan);
+
+       while (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
+               struct sk_buff *skb;
+               BT_DBG("Searching for skb with txseq %d (queue len %d)",
+                      chan->buffer_seq, skb_queue_len(&chan->srej_q));
+
+               skb = l2cap_ertm_seq_in_queue(&chan->srej_q, chan->buffer_seq);
+
+               if (!skb)
+                       break;
+
+               skb_unlink(skb, &chan->srej_q);
+               chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
+               err = l2cap_reassemble_sdu(chan, skb, &bt_cb(skb)->control);
+               if (err)
+                       break;
+       }
+
+       if (skb_queue_empty(&chan->srej_q)) {
+               chan->rx_state = L2CAP_RX_STATE_RECV;
+               l2cap_send_ack(chan);
+       }
+
+       return err;
 }
 
 static void l2cap_handle_srej(struct l2cap_chan *chan,