aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorGustavo F. Padovan <gustavo@las.ic.unicamp.br>2009-08-26 03:04:02 -0400
committerMarcel Holtmann <marcel@holtmann.org>2009-08-26 03:12:20 -0400
commit2246b2f1b43f3fbd128e72b129dcbbd3202cc592 (patch)
treeedfe82ab47829bb320c41c04289e2a01f23fba56 /net/bluetooth
parentca42a613c92d131ff02d5714419d58c36c3459f3 (diff)
Bluetooth: Handle L2CAP case when the remote receiver is busy
Implement all issues related to RemoteBusy in the RECV state table. Signed-off-by: Gustavo F. Padovan <gustavo@las.ic.unicamp.br> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/l2cap.c25
1 files changed, 23 insertions, 2 deletions
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 0a36c61c011f..40fbf5cb1f7e 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -1350,7 +1350,8 @@ static int l2cap_ertm_send(struct sock *sk)
1350 if (pi->conn_state & L2CAP_CONN_WAIT_F) 1350 if (pi->conn_state & L2CAP_CONN_WAIT_F)
1351 return 0; 1351 return 0;
1352 1352
1353 while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) { 1353 while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))
1354 && !(pi->conn_state & L2CAP_CONN_REMOTE_BUSY)) {
1354 tx_skb = skb_clone(skb, GFP_ATOMIC); 1355 tx_skb = skb_clone(skb, GFP_ATOMIC);
1355 1356
1356 if (pi->remote_max_tx && 1357 if (pi->remote_max_tx &&
@@ -3351,7 +3352,10 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str
3351 control |= L2CAP_SUPER_RCV_READY | 3352 control |= L2CAP_SUPER_RCV_READY |
3352 (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT); 3353 (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT);
3353 l2cap_send_sframe(l2cap_pi(sk), control); 3354 l2cap_send_sframe(l2cap_pi(sk), control);
3355 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3356
3354 } else if (rx_control & L2CAP_CTRL_FINAL) { 3357 } else if (rx_control & L2CAP_CTRL_FINAL) {
3358 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3355 pi->expected_ack_seq = tx_seq; 3359 pi->expected_ack_seq = tx_seq;
3356 l2cap_drop_acked_frames(sk); 3360 l2cap_drop_acked_frames(sk);
3357 3361
@@ -3366,13 +3370,19 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str
3366 } else { 3370 } else {
3367 pi->expected_ack_seq = tx_seq; 3371 pi->expected_ack_seq = tx_seq;
3368 l2cap_drop_acked_frames(sk); 3372 l2cap_drop_acked_frames(sk);
3369 if (pi->unacked_frames > 0) 3373
3374 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY)
3375 && (pi->unacked_frames > 0))
3370 __mod_retrans_timer(); 3376 __mod_retrans_timer();
3377
3371 l2cap_ertm_send(sk); 3378 l2cap_ertm_send(sk);
3379 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3372 } 3380 }
3373 break; 3381 break;
3374 3382
3375 case L2CAP_SUPER_REJECT: 3383 case L2CAP_SUPER_REJECT:
3384 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3385
3376 pi->expected_ack_seq = __get_reqseq(rx_control); 3386 pi->expected_ack_seq = __get_reqseq(rx_control);
3377 l2cap_drop_acked_frames(sk); 3387 l2cap_drop_acked_frames(sk);
3378 3388
@@ -3384,6 +3394,8 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str
3384 break; 3394 break;
3385 3395
3386 case L2CAP_SUPER_SELECT_REJECT: 3396 case L2CAP_SUPER_SELECT_REJECT:
3397 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3398
3387 if (rx_control & L2CAP_CTRL_POLL) { 3399 if (rx_control & L2CAP_CTRL_POLL) {
3388 l2cap_retransmit_frame(sk, tx_seq); 3400 l2cap_retransmit_frame(sk, tx_seq);
3389 pi->expected_ack_seq = tx_seq; 3401 pi->expected_ack_seq = tx_seq;
@@ -3410,6 +3422,15 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str
3410 break; 3422 break;
3411 3423
3412 case L2CAP_SUPER_RCV_NOT_READY: 3424 case L2CAP_SUPER_RCV_NOT_READY:
3425 pi->conn_state |= L2CAP_CONN_REMOTE_BUSY;
3426 pi->expected_ack_seq = tx_seq;
3427 l2cap_drop_acked_frames(sk);
3428
3429 del_timer(&l2cap_pi(sk)->retrans_timer);
3430 if (rx_control & L2CAP_CTRL_POLL) {
3431 u16 control = L2CAP_CTRL_FINAL | L2CAP_SUPER_RCV_READY;
3432 l2cap_send_sframe(l2cap_pi(sk), control);
3433 }
3413 break; 3434 break;
3414 } 3435 }
3415 3436