|
@@ -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,
|