diff options
-rw-r--r-- | include/net/bluetooth/l2cap.h | 2 | ||||
-rw-r--r-- | net/bluetooth/l2cap.c | 25 |
2 files changed, 25 insertions, 2 deletions
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 7ca614ac5d43..9516f4b4a3c2 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h | |||
@@ -373,6 +373,8 @@ struct l2cap_pinfo { | |||
373 | #define L2CAP_CONN_WAIT_F 0x04 | 373 | #define L2CAP_CONN_WAIT_F 0x04 |
374 | #define L2CAP_CONN_SREJ_ACT 0x08 | 374 | #define L2CAP_CONN_SREJ_ACT 0x08 |
375 | #define L2CAP_CONN_SEND_PBIT 0x10 | 375 | #define L2CAP_CONN_SEND_PBIT 0x10 |
376 | #define L2CAP_CONN_REMOTE_BUSY 0x20 | ||
377 | #define L2CAP_CONN_LOCAL_BUSY 0x40 | ||
376 | 378 | ||
377 | #define __mod_retrans_timer() mod_timer(&l2cap_pi(sk)->retrans_timer, \ | 379 | #define __mod_retrans_timer() mod_timer(&l2cap_pi(sk)->retrans_timer, \ |
378 | jiffies + msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO)); | 380 | jiffies + msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO)); |
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 | ||