aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/l2cap.c
diff options
context:
space:
mode:
authorGustavo F. Padovan <padovan@profusion.mobi>2010-06-18 19:37:33 -0400
committerMarcel Holtmann <marcel@holtmann.org>2010-07-21 13:39:05 -0400
commit95ffa97827371ede501615d9bd048eb5b49e8fe1 (patch)
tree0d20d43037c0430906673f9c36981eba4294c6b5 /net/bluetooth/l2cap.c
parentc13ffa620f15cb28d18268a773464cf51550fa9f (diff)
Bluetooth: Fix L2CAP control bit field corruption
When resending an I-frame, ERTM was reusing the control bits from the last time it was sent, that was causing a corruption in the new control field due to it dirty fields. This patches extracts only the SAR bits from the old field and reuse it to resend the packet, the others bits should be reset and receive the updated value. Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth/l2cap.c')
-rw-r--r--net/bluetooth/l2cap.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 4415eb48c6ae..c2fb26d9286c 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -1430,6 +1430,8 @@ static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq)
1430 tx_skb = skb_clone(skb, GFP_ATOMIC); 1430 tx_skb = skb_clone(skb, GFP_ATOMIC);
1431 bt_cb(skb)->retries++; 1431 bt_cb(skb)->retries++;
1432 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE); 1432 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
1433 control &= L2CAP_CTRL_SAR;
1434
1433 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT) 1435 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1434 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT); 1436 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
1435 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE); 1437 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
@@ -1465,6 +1467,8 @@ static int l2cap_ertm_send(struct sock *sk)
1465 bt_cb(skb)->retries++; 1467 bt_cb(skb)->retries++;
1466 1468
1467 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE); 1469 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
1470 control &= L2CAP_CTRL_SAR;
1471
1468 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) { 1472 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
1469 control |= L2CAP_CTRL_FINAL; 1473 control |= L2CAP_CTRL_FINAL;
1470 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT; 1474 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;