aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/l2cap.c
diff options
context:
space:
mode:
authorGustavo F. Padovan <padovan@profusion.mobi>2010-05-01 15:15:44 -0400
committerMarcel Holtmann <marcel@holtmann.org>2010-05-10 03:28:52 -0400
commitf11d676da4059c7888efca810ab300b931736a26 (patch)
tree68d4991bb0b85f803afedffe2309e1b3c46a876e /net/bluetooth/l2cap.c
parent9a9c6a34416b3743c09c00f3d6708d9df3c21629 (diff)
Bluetooth: Refactor l2cap_retransmit_frame()
Make the code flow cleaner and changes the function to void. It also fixes a potential NULL dereference with skb. Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi> Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth/l2cap.c')
-rw-r--r--net/bluetooth/l2cap.c53
1 files changed, 27 insertions, 26 deletions
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 7e74d5be16e3..1c35c328181d 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -1331,43 +1331,44 @@ static int l2cap_streaming_send(struct sock *sk)
1331 return 0; 1331 return 0;
1332} 1332}
1333 1333
1334static int l2cap_retransmit_frame(struct sock *sk, u8 tx_seq) 1334static void l2cap_retransmit_frame(struct sock *sk, u8 tx_seq)
1335{ 1335{
1336 struct l2cap_pinfo *pi = l2cap_pi(sk); 1336 struct l2cap_pinfo *pi = l2cap_pi(sk);
1337 struct sk_buff *skb, *tx_skb; 1337 struct sk_buff *skb, *tx_skb;
1338 u16 control, fcs; 1338 u16 control, fcs;
1339 1339
1340 skb = skb_peek(TX_QUEUE(sk)); 1340 skb = skb_peek(TX_QUEUE(sk));
1341 do { 1341 if (!skb)
1342 if (bt_cb(skb)->tx_seq != tx_seq) { 1342 return;
1343 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1344 break;
1345 skb = skb_queue_next(TX_QUEUE(sk), skb);
1346 continue;
1347 }
1348 1343
1349 if (pi->remote_max_tx && 1344 do {
1350 bt_cb(skb)->retries == pi->remote_max_tx) { 1345 if (bt_cb(skb)->tx_seq == tx_seq)
1351 l2cap_send_disconn_req(pi->conn, sk);
1352 break; 1346 break;
1353 }
1354 1347
1355 tx_skb = skb_clone(skb, GFP_ATOMIC); 1348 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1356 bt_cb(skb)->retries++; 1349 return;
1357 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
1358 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1359 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
1360 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1361 1350
1362 if (pi->fcs == L2CAP_FCS_CRC16) { 1351 } while ((skb = skb_queue_next(TX_QUEUE(sk), skb)));
1363 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1364 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1365 }
1366 1352
1367 l2cap_do_send(sk, tx_skb); 1353 if (pi->remote_max_tx &&
1368 break; 1354 bt_cb(skb)->retries == pi->remote_max_tx) {
1369 } while(1); 1355 l2cap_send_disconn_req(pi->conn, sk);
1370 return 0; 1356 return;
1357 }
1358
1359 tx_skb = skb_clone(skb, GFP_ATOMIC);
1360 bt_cb(skb)->retries++;
1361 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
1362 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1363 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
1364 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1365
1366 if (pi->fcs == L2CAP_FCS_CRC16) {
1367 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1368 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1369 }
1370
1371 l2cap_do_send(sk, tx_skb);
1371} 1372}
1372 1373
1373static int l2cap_ertm_send(struct sock *sk) 1374static int l2cap_ertm_send(struct sock *sk)