diff options
Diffstat (limited to 'net/bluetooth/l2cap_sock.c')
-rw-r--r-- | net/bluetooth/l2cap_sock.c | 65 |
1 files changed, 61 insertions, 4 deletions
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 | |||
711 | static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags) | 711 | static 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 | |||
758 | done: | ||
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 | ||
812 | static int l2cap_sock_recv_cb(void *data, struct sk_buff *skb) | 842 | static 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 | ||
819 | static void l2cap_sock_close_cb(void *data) | 871 | static 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 | } |