Bluetooth: Fix sending ReqSeq on I-frames
authorGustavo F. Padovan <gustavo@las.ic.unicamp.br>
Sat, 3 Oct 2009 05:34:38 +0000 (02:34 -0300)
committerMarcel Holtmann <marcel@holtmann.org>
Thu, 3 Dec 2009 18:34:23 +0000 (19:34 +0100)
As specified by ERTM spec an ERTM channel can acknowledge received
I-frames(the data frames) by sending an I-frame with the proper ReqSeq
value (i.e. ReqSeq is set to BufferSeq).  Until now we aren't setting the
ReqSeq value on I-frame control bits. That way we can save sending
S-frames(Supervise frames) only to acknowledge receipt of I-frames. It
is very helpful to the full-duplex channel.
ReqSeq is the packet sequence number sent in an acknowledgement frame to
acknowledge receipt of frames up to (ReqSeq - 1).
BufferSeq controls the receiver buffer, it is used to delay
acknowledgement of new frames to not cause buffer overflow. BufferSeq
value is not increased until frames are pulled by reassembly function.

Signed-off-by: Gustavo F. Padovan <gustavo@las.ic.unicamp.br>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
include/net/bluetooth/l2cap.h
net/bluetooth/l2cap.c

index 9516f4b4a3c235169404a1d589edfcb2eb378d46..327eb57dab512217677ed7f95b1f53af8fcec889 100644 (file)
@@ -324,7 +324,6 @@ struct l2cap_pinfo {
 
        __u8            next_tx_seq;
        __u8            expected_ack_seq;
-       __u8            req_seq;
        __u8            expected_tx_seq;
        __u8            buffer_seq;
        __u8            buffer_seq_srej;
index 2d5d37545b10d30e9161dbd7b77ea16025ebc7ec..78ab8811e5efe567055cf8d8d0e624f3da32868c 100644 (file)
@@ -1333,7 +1333,7 @@ static int l2cap_retransmit_frame(struct sock *sk, u8 tx_seq)
                tx_skb = skb_clone(skb, GFP_ATOMIC);
                bt_cb(skb)->retries++;
                control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
-               control |= (pi->req_seq << L2CAP_CTRL_REQSEQ_SHIFT)
+               control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
                                | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
                put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
 
@@ -1375,7 +1375,7 @@ static int l2cap_ertm_send(struct sock *sk)
                bt_cb(skb)->retries++;
 
                control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
-               control |= (pi->req_seq << L2CAP_CTRL_REQSEQ_SHIFT)
+               control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
                                | (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
                put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
 
@@ -3298,12 +3298,16 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str
 {
        struct l2cap_pinfo *pi = l2cap_pi(sk);
        u8 tx_seq = __get_txseq(rx_control);
+       u8 req_seq = __get_reqseq(rx_control);
        u16 tx_control = 0;
        u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
        int err = 0;
 
        BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
 
+       pi->expected_ack_seq = req_seq;
+       l2cap_drop_acked_frames(sk);
+
        if (tx_seq == pi->expected_tx_seq)
                goto expected;