aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorGustavo F. Padovan <padovan@profusion.mobi>2010-05-01 15:15:37 -0400
committerMarcel Holtmann <marcel@holtmann.org>2010-05-10 03:28:47 -0400
commit9e917af13d59182f95bbb5483dc0c4254dfb7944 (patch)
tree03f3fffbce196c30e7ae456b838f5cefcb2a681f /net
parent36f2fd585f43199f006a3b5ff84e95815102cd31 (diff)
Bluetooth: Implement SendAck() Action on ERTM.
Shall be used to ack received frames, It must decide type of acknowledgment between a RR frame, a RNR frame or transmission of pending I-frames. It also modifies l2cap_ertm_send() to report the number of frames sent. 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')
-rw-r--r--net/bluetooth/l2cap.c41
1 files changed, 29 insertions, 12 deletions
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 2e354d29f102..0a739ef167c2 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -352,6 +352,11 @@ static inline int l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)
352 count = min_t(unsigned int, conn->mtu, hlen); 352 count = min_t(unsigned int, conn->mtu, hlen);
353 control |= L2CAP_CTRL_FRAME_TYPE; 353 control |= L2CAP_CTRL_FRAME_TYPE;
354 354
355 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
356 control |= L2CAP_CTRL_FINAL;
357 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
358 }
359
355 skb = bt_skb_alloc(count, GFP_ATOMIC); 360 skb = bt_skb_alloc(count, GFP_ATOMIC);
356 if (!skb) 361 if (!skb)
357 return -ENOMEM; 362 return -ENOMEM;
@@ -1364,7 +1369,7 @@ static int l2cap_ertm_send(struct sock *sk)
1364 struct sk_buff *skb, *tx_skb; 1369 struct sk_buff *skb, *tx_skb;
1365 struct l2cap_pinfo *pi = l2cap_pi(sk); 1370 struct l2cap_pinfo *pi = l2cap_pi(sk);
1366 u16 control, fcs; 1371 u16 control, fcs;
1367 int err; 1372 int err, nsent = 0;
1368 1373
1369 if (pi->conn_state & L2CAP_CONN_WAIT_F) 1374 if (pi->conn_state & L2CAP_CONN_WAIT_F)
1370 return 0; 1375 return 0;
@@ -1414,8 +1419,27 @@ static int l2cap_ertm_send(struct sock *sk)
1414 sk->sk_send_head = NULL; 1419 sk->sk_send_head = NULL;
1415 else 1420 else
1416 sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb); 1421 sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
1422
1423 nsent++;
1417 } 1424 }
1418 1425
1426 return nsent;
1427}
1428
1429static int l2cap_send_ack(struct l2cap_pinfo *pi)
1430{
1431 struct sock *sk = (struct sock *)pi;
1432 u16 control = 0;
1433
1434 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1435
1436 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
1437 control |= L2CAP_SUPER_RCV_NOT_READY;
1438 return l2cap_send_sframe(pi, control);
1439 } else if (l2cap_ertm_send(sk) == 0) {
1440 control |= L2CAP_SUPER_RCV_READY;
1441 return l2cap_send_sframe(pi, control);
1442 }
1419 return 0; 1443 return 0;
1420} 1444}
1421 1445
@@ -1678,7 +1702,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
1678 else 1702 else
1679 err = l2cap_ertm_send(sk); 1703 err = l2cap_ertm_send(sk);
1680 1704
1681 if (!err) 1705 if (err >= 0)
1682 err = len; 1706 err = len;
1683 break; 1707 break;
1684 1708
@@ -3178,10 +3202,6 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
3178 if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) && 3202 if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
3179 pi->frames_sent == 0) { 3203 pi->frames_sent == 0) {
3180 control |= L2CAP_SUPER_RCV_READY; 3204 control |= L2CAP_SUPER_RCV_READY;
3181 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
3182 control |= L2CAP_CTRL_FINAL;
3183 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
3184 }
3185 l2cap_send_sframe(pi, control); 3205 l2cap_send_sframe(pi, control);
3186 } 3206 }
3187} 3207}
@@ -3362,7 +3382,6 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str
3362 struct l2cap_pinfo *pi = l2cap_pi(sk); 3382 struct l2cap_pinfo *pi = l2cap_pi(sk);
3363 u8 tx_seq = __get_txseq(rx_control); 3383 u8 tx_seq = __get_txseq(rx_control);
3364 u8 req_seq = __get_reqseq(rx_control); 3384 u8 req_seq = __get_reqseq(rx_control);
3365 u16 tx_control = 0;
3366 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT; 3385 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
3367 int err = 0; 3386 int err = 0;
3368 3387
@@ -3449,11 +3468,9 @@ expected:
3449 return err; 3468 return err;
3450 3469
3451 pi->num_to_ack = (pi->num_to_ack + 1) % L2CAP_DEFAULT_NUM_TO_ACK; 3470 pi->num_to_ack = (pi->num_to_ack + 1) % L2CAP_DEFAULT_NUM_TO_ACK;
3452 if (pi->num_to_ack == L2CAP_DEFAULT_NUM_TO_ACK - 1) { 3471 if (pi->num_to_ack == L2CAP_DEFAULT_NUM_TO_ACK - 1)
3453 tx_control |= L2CAP_SUPER_RCV_READY; 3472 l2cap_send_ack(pi);
3454 tx_control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; 3473
3455 l2cap_send_sframe(pi, tx_control);
3456 }
3457 return 0; 3474 return 0;
3458} 3475}
3459 3476