aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGustavo F. Padovan <padovan@profusion.mobi>2010-06-21 18:39:50 -0400
committerMarcel Holtmann <marcel@holtmann.org>2010-07-21 13:39:09 -0400
commit712132eb541e4a76afad97898dc0ce6b6c0032d8 (patch)
tree5e4b44c035a02c55563265f1e8036bfb67ece9d4
parent218bb9dfd21472128f86b38ad2eab123205c2991 (diff)
Bluetooth: Improve ERTM local busy handling
Now we also check if can push skb userspace just after receive a new skb instead of only wait the l2cap_busy_work wake up from time to time to check the local busy condition. Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r--net/bluetooth/l2cap.c83
1 files changed, 47 insertions, 36 deletions
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index cf4481f7f566..6b839d682143 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -3606,6 +3606,46 @@ disconnect:
3606 return 0; 3606 return 0;
3607} 3607}
3608 3608
3609static int l2cap_try_push_rx_skb(struct sock *sk)
3610{
3611 struct l2cap_pinfo *pi = l2cap_pi(sk);
3612 struct sk_buff *skb;
3613 u16 control;
3614 int err;
3615
3616 while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) {
3617 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
3618 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
3619 if (err < 0) {
3620 skb_queue_head(BUSY_QUEUE(sk), skb);
3621 return -EBUSY;
3622 }
3623
3624 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
3625 }
3626
3627 if (!(pi->conn_state & L2CAP_CONN_RNR_SENT))
3628 goto done;
3629
3630 control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3631 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
3632 l2cap_send_sframe(pi, control);
3633 l2cap_pi(sk)->retry_count = 1;
3634
3635 del_timer(&pi->retrans_timer);
3636 __mod_monitor_timer();
3637
3638 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
3639
3640done:
3641 pi->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
3642 pi->conn_state &= ~L2CAP_CONN_RNR_SENT;
3643
3644 BT_DBG("sk %p, Exit local busy", sk);
3645
3646 return 0;
3647}
3648
3609static void l2cap_busy_work(struct work_struct *work) 3649static void l2cap_busy_work(struct work_struct *work)
3610{ 3650{
3611 DECLARE_WAITQUEUE(wait, current); 3651 DECLARE_WAITQUEUE(wait, current);
@@ -3614,7 +3654,6 @@ static void l2cap_busy_work(struct work_struct *work)
3614 struct sock *sk = (struct sock *)pi; 3654 struct sock *sk = (struct sock *)pi;
3615 int n_tries = 0, timeo = HZ/5, err; 3655 int n_tries = 0, timeo = HZ/5, err;
3616 struct sk_buff *skb; 3656 struct sk_buff *skb;
3617 u16 control;
3618 3657
3619 lock_sock(sk); 3658 lock_sock(sk);
3620 3659
@@ -3625,7 +3664,7 @@ static void l2cap_busy_work(struct work_struct *work)
3625 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) { 3664 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3626 err = -EBUSY; 3665 err = -EBUSY;
3627 l2cap_send_disconn_req(pi->conn, sk, EBUSY); 3666 l2cap_send_disconn_req(pi->conn, sk, EBUSY);
3628 goto done; 3667 break;
3629 } 3668 }
3630 3669
3631 if (!timeo) 3670 if (!timeo)
@@ -3633,7 +3672,7 @@ static void l2cap_busy_work(struct work_struct *work)
3633 3672
3634 if (signal_pending(current)) { 3673 if (signal_pending(current)) {
3635 err = sock_intr_errno(timeo); 3674 err = sock_intr_errno(timeo);
3636 goto done; 3675 break;
3637 } 3676 }
3638 3677
3639 release_sock(sk); 3678 release_sock(sk);
@@ -3642,42 +3681,12 @@ static void l2cap_busy_work(struct work_struct *work)
3642 3681
3643 err = sock_error(sk); 3682 err = sock_error(sk);
3644 if (err) 3683 if (err)
3645 goto done; 3684 break;
3646
3647 while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) {
3648 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
3649 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
3650 if (err < 0) {
3651 skb_queue_head(BUSY_QUEUE(sk), skb);
3652 break;
3653 }
3654
3655 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
3656 }
3657 3685
3658 if (!skb) 3686 if (l2cap_try_push_rx_skb(sk) == 0)
3659 break; 3687 break;
3660 } 3688 }
3661 3689
3662 if (!(pi->conn_state & L2CAP_CONN_RNR_SENT))
3663 goto done;
3664
3665 control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3666 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
3667 l2cap_send_sframe(pi, control);
3668 l2cap_pi(sk)->retry_count = 1;
3669
3670 del_timer(&pi->retrans_timer);
3671 __mod_monitor_timer();
3672
3673 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
3674
3675done:
3676 pi->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
3677 pi->conn_state &= ~L2CAP_CONN_RNR_SENT;
3678
3679 BT_DBG("sk %p, Exit local busy", sk);
3680
3681 set_current_state(TASK_RUNNING); 3690 set_current_state(TASK_RUNNING);
3682 remove_wait_queue(sk_sleep(sk), &wait); 3691 remove_wait_queue(sk_sleep(sk), &wait);
3683 3692
@@ -3692,7 +3701,9 @@ static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control)
3692 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) { 3701 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
3693 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT; 3702 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3694 __skb_queue_tail(BUSY_QUEUE(sk), skb); 3703 __skb_queue_tail(BUSY_QUEUE(sk), skb);
3695 return -EBUSY; 3704 return l2cap_try_push_rx_skb(sk);
3705
3706
3696 } 3707 }
3697 3708
3698 err = l2cap_ertm_reassembly_sdu(sk, skb, control); 3709 err = l2cap_ertm_reassembly_sdu(sk, skb, control);