aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorMat Martineau <mathewm@codeaurora.org>2011-07-07 12:39:02 -0400
committerGustavo F. Padovan <padovan@profusion.mobi>2011-07-07 14:28:56 -0400
commite328140fdacbba43292a59a22fb55d9185288318 (patch)
tree43eb760529846562e6e75c25cd39a8317142eac7 /net
parent26f880d221302b5d061185d8a6795bb532693bf3 (diff)
Bluetooth: Use event-driven approach for handling ERTM receive buffer
This change moves most L2CAP ERTM receive buffer handling out of the L2CAP core and in to the socket code. It's up to the higher layer (the socket code, in this case) to tell the core when its buffer is full or has space available. The recv op should always accept incoming ERTM data or else the connection will go down. Within the socket layer, an skb that does not fit in the socket receive buffer will be temporarily stored. When the socket is read from, that skb will be placed in the receive buffer if possible. Once adequate buffer space becomes available, the L2CAP core is informed and the ERTM local busy state is cleared. Receive buffer management for non-ERTM modes is unchanged. Signed-off-by: Mat Martineau <mathewm@codeaurora.org> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/l2cap_core.c41
-rw-r--r--net/bluetooth/l2cap_sock.c65
2 files changed, 87 insertions, 19 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index f7ada4a2cc5d..ea9c7d061046 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -3350,21 +3350,21 @@ static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 c
3350 } 3350 }
3351 3351
3352 err = l2cap_ertm_reassembly_sdu(chan, skb, control); 3352 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
3353 if (err >= 0) { 3353 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
3354 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
3355 return err;
3356 }
3357
3358 l2cap_ertm_enter_local_busy(chan);
3359
3360 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3361 __skb_queue_tail(&chan->busy_q, skb);
3362
3363 queue_work(_busy_wq, &chan->busy_work);
3364 3354
3365 return err; 3355 return err;
3366} 3356}
3367 3357
3358void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
3359{
3360 if (chan->mode == L2CAP_MODE_ERTM) {
3361 if (busy)
3362 l2cap_ertm_enter_local_busy(chan);
3363 else
3364 l2cap_ertm_exit_local_busy(chan);
3365 }
3366}
3367
3368static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control) 3368static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
3369{ 3369{
3370 struct sk_buff *_skb; 3370 struct sk_buff *_skb;
@@ -3463,13 +3463,22 @@ static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
3463 struct sk_buff *skb; 3463 struct sk_buff *skb;
3464 u16 control; 3464 u16 control;
3465 3465
3466 while ((skb = skb_peek(&chan->srej_q))) { 3466 while ((skb = skb_peek(&chan->srej_q)) &&
3467 !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3468 int err;
3469
3467 if (bt_cb(skb)->tx_seq != tx_seq) 3470 if (bt_cb(skb)->tx_seq != tx_seq)
3468 break; 3471 break;
3469 3472
3470 skb = skb_dequeue(&chan->srej_q); 3473 skb = skb_dequeue(&chan->srej_q);
3471 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT; 3474 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
3472 l2cap_ertm_reassembly_sdu(chan, skb, control); 3475 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
3476
3477 if (err < 0) {
3478 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3479 break;
3480 }
3481
3473 chan->buffer_seq_srej = 3482 chan->buffer_seq_srej =
3474 (chan->buffer_seq_srej + 1) % 64; 3483 (chan->buffer_seq_srej + 1) % 64;
3475 tx_seq = (tx_seq + 1) % 64; 3484 tx_seq = (tx_seq + 1) % 64;
@@ -3625,8 +3634,10 @@ expected:
3625 } 3634 }
3626 3635
3627 err = l2cap_push_rx_skb(chan, skb, rx_control); 3636 err = l2cap_push_rx_skb(chan, skb, rx_control);
3628 if (err < 0) 3637 if (err < 0) {
3629 return 0; 3638 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3639 return err;
3640 }
3630 3641
3631 if (rx_control & L2CAP_CTRL_FINAL) { 3642 if (rx_control & L2CAP_CTRL_FINAL) {
3632 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state)) 3643 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 39082d4e77ce..146b614d10ed 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -711,13 +711,15 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
711static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags) 711static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags)
712{ 712{
713 struct sock *sk = sock->sk; 713 struct sock *sk = sock->sk;
714 struct l2cap_pinfo *pi = l2cap_pi(sk);
715 int err;
714 716
715 lock_sock(sk); 717 lock_sock(sk);
716 718
717 if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) { 719 if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) {
718 sk->sk_state = BT_CONFIG; 720 sk->sk_state = BT_CONFIG;
719 721
720 __l2cap_connect_rsp_defer(l2cap_pi(sk)->chan); 722 __l2cap_connect_rsp_defer(pi->chan);
721 release_sock(sk); 723 release_sock(sk);
722 return 0; 724 return 0;
723 } 725 }
@@ -725,9 +727,37 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct ms
725 release_sock(sk); 727 release_sock(sk);
726 728
727 if (sock->type == SOCK_STREAM) 729 if (sock->type == SOCK_STREAM)
728 return bt_sock_stream_recvmsg(iocb, sock, msg, len, flags); 730 err = bt_sock_stream_recvmsg(iocb, sock, msg, len, flags);
731 else
732 err = bt_sock_recvmsg(iocb, sock, msg, len, flags);
733
734 if (pi->chan->mode != L2CAP_MODE_ERTM)
735 return err;
736
737 /* Attempt to put pending rx data in the socket buffer */
738
739 lock_sock(sk);
740
741 if (!test_bit(CONN_LOCAL_BUSY, &pi->chan->conn_state))
742 goto done;
743
744 if (pi->rx_busy_skb) {
745 if (!sock_queue_rcv_skb(sk, pi->rx_busy_skb))
746 pi->rx_busy_skb = NULL;
747 else
748 goto done;
749 }
729 750
730 return bt_sock_recvmsg(iocb, sock, msg, len, flags); 751 /* Restore data flow when half of the receive buffer is
752 * available. This avoids resending large numbers of
753 * frames.
754 */
755 if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf >> 1)
756 l2cap_chan_busy(pi->chan, 0);
757
758done:
759 release_sock(sk);
760 return err;
731} 761}
732 762
733/* Kill socket (only if zapped and orphan) 763/* Kill socket (only if zapped and orphan)
@@ -811,9 +841,31 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(void *data)
811 841
812static int l2cap_sock_recv_cb(void *data, struct sk_buff *skb) 842static int l2cap_sock_recv_cb(void *data, struct sk_buff *skb)
813{ 843{
844 int err;
814 struct sock *sk = data; 845 struct sock *sk = data;
846 struct l2cap_pinfo *pi = l2cap_pi(sk);
815 847
816 return sock_queue_rcv_skb(sk, skb); 848 if (pi->rx_busy_skb)
849 return -ENOMEM;
850
851 err = sock_queue_rcv_skb(sk, skb);
852
853 /* For ERTM, handle one skb that doesn't fit into the recv
854 * buffer. This is important to do because the data frames
855 * have already been acked, so the skb cannot be discarded.
856 *
857 * Notify the l2cap core that the buffer is full, so the
858 * LOCAL_BUSY state is entered and no more frames are
859 * acked and reassembled until there is buffer space
860 * available.
861 */
862 if (err < 0 && pi->chan->mode == L2CAP_MODE_ERTM) {
863 pi->rx_busy_skb = skb;
864 l2cap_chan_busy(pi->chan, 1);
865 err = 0;
866 }
867
868 return err;
817} 869}
818 870
819static void l2cap_sock_close_cb(void *data) 871static void l2cap_sock_close_cb(void *data)
@@ -842,6 +894,11 @@ static void l2cap_sock_destruct(struct sock *sk)
842{ 894{
843 BT_DBG("sk %p", sk); 895 BT_DBG("sk %p", sk);
844 896
897 if (l2cap_pi(sk)->rx_busy_skb) {
898 kfree_skb(l2cap_pi(sk)->rx_busy_skb);
899 l2cap_pi(sk)->rx_busy_skb = NULL;
900 }
901
845 skb_queue_purge(&sk->sk_receive_queue); 902 skb_queue_purge(&sk->sk_receive_queue);
846 skb_queue_purge(&sk->sk_write_queue); 903 skb_queue_purge(&sk->sk_write_queue);
847} 904}