diff options
author | Gustavo F. Padovan <padovan@profusion.mobi> | 2010-05-01 15:15:44 -0400 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2010-05-10 03:28:52 -0400 |
commit | f11d676da4059c7888efca810ab300b931736a26 (patch) | |
tree | 68d4991bb0b85f803afedffe2309e1b3c46a876e | |
parent | 9a9c6a34416b3743c09c00f3d6708d9df3c21629 (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>
-rw-r--r-- | net/bluetooth/l2cap.c | 53 |
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 | ||
1334 | static int l2cap_retransmit_frame(struct sock *sk, u8 tx_seq) | 1334 | static 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 | ||
1373 | static int l2cap_ertm_send(struct sock *sk) | 1374 | static int l2cap_ertm_send(struct sock *sk) |