From 73ae8695d17b79cd6c37c2057093234d8260652a Mon Sep 17 00:00:00 2001 From: Mat Martineau Date: Thu, 17 May 2012 20:53:33 -0700 Subject: [PATCH] --- yaml --- r: 314388 b: refs/heads/master c: 3733937d96f3fe4dfc3b8da43385d739e905ff41 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/net/bluetooth/l2cap_core.c | 48 +++++++++++++++++++++----------- 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/[refs] b/[refs] index f99c2b74317e..957c09727bc1 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 608bcc6d70850be9e3aa7c3831045304a2a65fbb +refs/heads/master: 3733937d96f3fe4dfc3b8da43385d739e905ff41 diff --git a/trunk/net/bluetooth/l2cap_core.c b/trunk/net/bluetooth/l2cap_core.c index c5232d25da52..25edccff4c94 100644 --- a/trunk/net/bluetooth/l2cap_core.c +++ b/trunk/net/bluetooth/l2cap_core.c @@ -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;