summaryrefslogtreecommitdiffstats
path: root/net/bluetooth/l2cap.c
diff options
context:
space:
mode:
authorGustavo F. Padovan2010-06-01 23:52:58 +0200
committerMarcel Holtmann2010-07-21 19:39:04 +0200
commit6e2b6722abaa3f6042357e11f465488b7c12f94c (patch)
treef3c7b190298f4f779bc35eb680e2306da25e06aa /net/bluetooth/l2cap.c
parentBluetooth: Only check SAR bits if frame is an I-frame (diff)
downloadkernel-qcow2-linux-6e2b6722abaa3f6042357e11f465488b7c12f94c.tar.gz
kernel-qcow2-linux-6e2b6722abaa3f6042357e11f465488b7c12f94c.tar.xz
kernel-qcow2-linux-6e2b6722abaa3f6042357e11f465488b7c12f94c.zip
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.c12
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)
u16 control, fcs;
int nsent = 0;
- if (pi->conn_state & L2CAP_CONN_WAIT_F)
- return 0;
- while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk)) &&
- !(pi->conn_state & L2CAP_CONN_REMOTE_BUSY)) {
+ while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) {
if (pi->remote_max_tx &&
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
if (pi->mode == L2CAP_MODE_STREAMING) {
err = l2cap_streaming_send(sk);
} else {
+ if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY &&
+ pi->conn_state && L2CAP_CONN_WAIT_F) {
+ err = len;
+ break;
+ }
spin_lock_bh(&pi->send_lock);
err = l2cap_ertm_send(sk);
spin_unlock_bh(&pi->send_lock);
@@ -3378,8 +3380,6 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY && pi->unacked_frames > 0)
__mod_retrans_timer();
- pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
-
spin_lock_bh(&pi->send_lock);
l2cap_ertm_send(sk);
spin_unlock_bh(&pi->send_lock);