aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorGustavo F. Padovan <gustavo@las.ic.unicamp.br>2009-10-03 01:34:38 -0400
committerMarcel Holtmann <marcel@holtmann.org>2009-12-03 13:34:23 -0500
commit9f121a5a80b4417c6db5a35e26d2e79c29c3fc0d (patch)
tree8e01df10e3e640c0f76b4c3f380db351543900bb /net
parent889a3ca466018ab68363c3168993793bc2d984f1 (diff)
Bluetooth: Fix sending ReqSeq on I-frames
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>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/l2cap.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 2d5d37545b10..78ab8811e5ef 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -1333,7 +1333,7 @@ static int l2cap_retransmit_frame(struct sock *sk, u8 tx_seq)
1333 tx_skb = skb_clone(skb, GFP_ATOMIC); 1333 tx_skb = skb_clone(skb, GFP_ATOMIC);
1334 bt_cb(skb)->retries++; 1334 bt_cb(skb)->retries++;
1335 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE); 1335 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
1336 control |= (pi->req_seq << L2CAP_CTRL_REQSEQ_SHIFT) 1336 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1337 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT); 1337 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
1338 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE); 1338 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1339 1339
@@ -1375,7 +1375,7 @@ static int l2cap_ertm_send(struct sock *sk)
1375 bt_cb(skb)->retries++; 1375 bt_cb(skb)->retries++;
1376 1376
1377 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE); 1377 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
1378 control |= (pi->req_seq << L2CAP_CTRL_REQSEQ_SHIFT) 1378 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1379 | (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT); 1379 | (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
1380 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE); 1380 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1381 1381
@@ -3298,12 +3298,16 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str
3298{ 3298{
3299 struct l2cap_pinfo *pi = l2cap_pi(sk); 3299 struct l2cap_pinfo *pi = l2cap_pi(sk);
3300 u8 tx_seq = __get_txseq(rx_control); 3300 u8 tx_seq = __get_txseq(rx_control);
3301 u8 req_seq = __get_reqseq(rx_control);
3301 u16 tx_control = 0; 3302 u16 tx_control = 0;
3302 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT; 3303 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
3303 int err = 0; 3304 int err = 0;
3304 3305
3305 BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len); 3306 BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
3306 3307
3308 pi->expected_ack_seq = req_seq;
3309 l2cap_drop_acked_frames(sk);
3310
3307 if (tx_seq == pi->expected_tx_seq) 3311 if (tx_seq == pi->expected_tx_seq)
3308 goto expected; 3312 goto expected;
3309 3313