diff options
author | Gustavo F. Padovan <gustavo@las.ic.unicamp.br> | 2009-08-26 03:04:02 -0400 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2009-08-26 03:12:20 -0400 |
commit | 2246b2f1b43f3fbd128e72b129dcbbd3202cc592 (patch) | |
tree | edfe82ab47829bb320c41c04289e2a01f23fba56 /net/bluetooth/l2cap.c | |
parent | ca42a613c92d131ff02d5714419d58c36c3459f3 (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/l2cap.c')
-rw-r--r-- | net/bluetooth/l2cap.c | 25 |
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 | ||