diff options
author | Gustavo F. Padovan <padovan@profusion.mobi> | 2010-06-01 17:52:58 -0400 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2010-07-21 13:39:04 -0400 |
commit | 6e2b6722abaa3f6042357e11f465488b7c12f94c (patch) | |
tree | f3c7b190298f4f779bc35eb680e2306da25e06aa /net/bluetooth/l2cap.c | |
parent | bc1b1f8bee63966649dd5ac7d10d31a6556bf19b (diff) |
Bluetooth: Fix bug in l2cap_ertm_send() behavior
This patch makes l2cap_ertm_send() similar to the Send-Data action of
the ERTM spec. We shall not check for RemoteBusy or WAIT_F state
inside l2cap_ertm_send().
Such checks were causing a bug in the retransmission logic of ERTM and
making ERTM stalls until the ACL is dropped.
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/bluetooth/l2cap.c')
-rw-r--r-- | net/bluetooth/l2cap.c | 12 |
1 files changed, 6 insertions, 6 deletions
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 108c2f290ac5..69f098d98141 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c | |||
@@ -1415,11 +1415,8 @@ static int l2cap_ertm_send(struct sock *sk) | |||
1415 | u16 control, fcs; | 1415 | u16 control, fcs; |
1416 | int nsent = 0; | 1416 | int nsent = 0; |
1417 | 1417 | ||
1418 | if (pi->conn_state & L2CAP_CONN_WAIT_F) | ||
1419 | return 0; | ||
1420 | 1418 | ||
1421 | while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk)) && | 1419 | while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) { |
1422 | !(pi->conn_state & L2CAP_CONN_REMOTE_BUSY)) { | ||
1423 | 1420 | ||
1424 | if (pi->remote_max_tx && | 1421 | if (pi->remote_max_tx && |
1425 | bt_cb(skb)->retries == pi->remote_max_tx) { | 1422 | bt_cb(skb)->retries == pi->remote_max_tx) { |
@@ -1792,6 +1789,11 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms | |||
1792 | if (pi->mode == L2CAP_MODE_STREAMING) { | 1789 | if (pi->mode == L2CAP_MODE_STREAMING) { |
1793 | err = l2cap_streaming_send(sk); | 1790 | err = l2cap_streaming_send(sk); |
1794 | } else { | 1791 | } else { |
1792 | if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY && | ||
1793 | pi->conn_state && L2CAP_CONN_WAIT_F) { | ||
1794 | err = len; | ||
1795 | break; | ||
1796 | } | ||
1795 | spin_lock_bh(&pi->send_lock); | 1797 | spin_lock_bh(&pi->send_lock); |
1796 | err = l2cap_ertm_send(sk); | 1798 | err = l2cap_ertm_send(sk); |
1797 | spin_unlock_bh(&pi->send_lock); | 1799 | spin_unlock_bh(&pi->send_lock); |
@@ -3378,8 +3380,6 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk) | |||
3378 | if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY && pi->unacked_frames > 0) | 3380 | if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY && pi->unacked_frames > 0) |
3379 | __mod_retrans_timer(); | 3381 | __mod_retrans_timer(); |
3380 | 3382 | ||
3381 | pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; | ||
3382 | |||
3383 | spin_lock_bh(&pi->send_lock); | 3383 | spin_lock_bh(&pi->send_lock); |
3384 | l2cap_ertm_send(sk); | 3384 | l2cap_ertm_send(sk); |
3385 | spin_unlock_bh(&pi->send_lock); | 3385 | spin_unlock_bh(&pi->send_lock); |