Bluetooth: Refactor l2cap_streaming_send
authorMat Martineau <mathewm@codeaurora.org>
Fri, 18 May 2012 03:53:33 +0000 (20:53 -0700)
committerJohan Hedberg <johan.hedberg@intel.com>
Tue, 5 Jun 2012 03:34:02 +0000 (06:34 +0300)
This new implementation uses struct l2cap_ctrl to compose the
streaming mode headers.

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

index c5232d25da52fc03736a45242543c8c98f32e641..25edccff4c942c181d9dd48602fd8655e125f625 100644 (file)
@@ -1650,29 +1650,45 @@ static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
                __clear_retrans_timer(chan);
 }
 
-static void l2cap_streaming_send(struct l2cap_chan *chan)
+static int l2cap_streaming_send(struct l2cap_chan *chan,
+                               struct sk_buff_head *skbs)
 {
        struct sk_buff *skb;
-       u32 control;
-       u16 fcs;
+       struct l2cap_ctrl *control;
 
-       while ((skb = skb_dequeue(&chan->tx_q))) {
-               control = __get_control(chan, skb->data + L2CAP_HDR_SIZE);
-               control |= __set_txseq(chan, chan->next_tx_seq);
-               control |= __set_ctrl_sar(chan, bt_cb(skb)->control.sar);
-               __put_control(chan, control, skb->data + L2CAP_HDR_SIZE);
+       BT_DBG("chan %p, skbs %p", chan, skbs);
+
+       if (chan->state != BT_CONNECTED)
+               return -ENOTCONN;
+
+       skb_queue_splice_tail_init(skbs, &chan->tx_q);
+
+       while (!skb_queue_empty(&chan->tx_q)) {
+
+               skb = skb_dequeue(&chan->tx_q);
+
+               bt_cb(skb)->control.retries = 1;
+               control = &bt_cb(skb)->control;
+
+               control->reqseq = 0;
+               control->txseq = chan->next_tx_seq;
+
+               __pack_control(chan, control, skb);
 
                if (chan->fcs == L2CAP_FCS_CRC16) {
-                       fcs = crc16(0, (u8 *)skb->data,
-                                               skb->len - L2CAP_FCS_SIZE);
-                       put_unaligned_le16(fcs,
-                                       skb->data + skb->len - L2CAP_FCS_SIZE);
+                       u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
+                       put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
                }
 
                l2cap_do_send(chan, skb);
 
+               BT_DBG("Sent txseq %d", (int)control->txseq);
+
                chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
+               chan->frames_sent++;
        }
+
+       return 0;
 }
 
 static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
@@ -2136,13 +2152,11 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
                if (err)
                        break;
 
-               if (chan->mode == L2CAP_MODE_ERTM) {
+               if (chan->mode == L2CAP_MODE_ERTM)
                        err = l2cap_tx(chan, 0, &seg_queue,
                                       L2CAP_EV_DATA_REQUEST);
-               } else {
-                       skb_queue_splice_tail_init(&seg_queue, &chan->tx_q);
-                       l2cap_streaming_send(chan);
-               }
+               else
+                       err = l2cap_streaming_send(chan, &seg_queue);
 
                if (!err)
                        err = len;