diff options
Diffstat (limited to 'net/bluetooth/l2cap_sock.c')
| -rw-r--r-- | net/bluetooth/l2cap_sock.c | 54 |
1 files changed, 45 insertions, 9 deletions
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 401d9428ae4c..c4fe583b0af6 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
| @@ -125,13 +125,15 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al | |||
| 125 | 125 | ||
| 126 | err = l2cap_chan_connect(chan, la.l2_psm, la.l2_cid, &la.l2_bdaddr); | 126 | err = l2cap_chan_connect(chan, la.l2_psm, la.l2_cid, &la.l2_bdaddr); |
| 127 | if (err) | 127 | if (err) |
| 128 | goto done; | 128 | return err; |
| 129 | |||
| 130 | lock_sock(sk); | ||
| 129 | 131 | ||
| 130 | err = bt_sock_wait_state(sk, BT_CONNECTED, | 132 | err = bt_sock_wait_state(sk, BT_CONNECTED, |
| 131 | sock_sndtimeo(sk, flags & O_NONBLOCK)); | 133 | sock_sndtimeo(sk, flags & O_NONBLOCK)); |
| 132 | done: | 134 | |
| 133 | if (sock_owned_by_user(sk)) | 135 | release_sock(sk); |
| 134 | release_sock(sk); | 136 | |
| 135 | return err; | 137 | return err; |
| 136 | } | 138 | } |
| 137 | 139 | ||
| @@ -783,7 +785,7 @@ static void l2cap_sock_kill(struct sock *sk) | |||
| 783 | if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket) | 785 | if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket) |
| 784 | return; | 786 | return; |
| 785 | 787 | ||
| 786 | BT_DBG("sk %p state %d", sk, sk->sk_state); | 788 | BT_DBG("sk %p state %s", sk, state_to_string(sk->sk_state)); |
| 787 | 789 | ||
| 788 | /* Kill poor orphan */ | 790 | /* Kill poor orphan */ |
| 789 | 791 | ||
| @@ -795,7 +797,8 @@ static void l2cap_sock_kill(struct sock *sk) | |||
| 795 | static int l2cap_sock_shutdown(struct socket *sock, int how) | 797 | static int l2cap_sock_shutdown(struct socket *sock, int how) |
| 796 | { | 798 | { |
| 797 | struct sock *sk = sock->sk; | 799 | struct sock *sk = sock->sk; |
| 798 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; | 800 | struct l2cap_chan *chan; |
| 801 | struct l2cap_conn *conn; | ||
| 799 | int err = 0; | 802 | int err = 0; |
| 800 | 803 | ||
| 801 | BT_DBG("sock %p, sk %p", sock, sk); | 804 | BT_DBG("sock %p, sk %p", sock, sk); |
| @@ -803,13 +806,24 @@ static int l2cap_sock_shutdown(struct socket *sock, int how) | |||
| 803 | if (!sk) | 806 | if (!sk) |
| 804 | return 0; | 807 | return 0; |
| 805 | 808 | ||
| 809 | chan = l2cap_pi(sk)->chan; | ||
| 810 | conn = chan->conn; | ||
| 811 | |||
| 812 | if (conn) | ||
| 813 | mutex_lock(&conn->chan_lock); | ||
| 814 | |||
| 815 | l2cap_chan_lock(chan); | ||
| 806 | lock_sock(sk); | 816 | lock_sock(sk); |
| 817 | |||
| 807 | if (!sk->sk_shutdown) { | 818 | if (!sk->sk_shutdown) { |
| 808 | if (chan->mode == L2CAP_MODE_ERTM) | 819 | if (chan->mode == L2CAP_MODE_ERTM) |
| 809 | err = __l2cap_wait_ack(sk); | 820 | err = __l2cap_wait_ack(sk); |
| 810 | 821 | ||
| 811 | sk->sk_shutdown = SHUTDOWN_MASK; | 822 | sk->sk_shutdown = SHUTDOWN_MASK; |
| 823 | |||
| 824 | release_sock(sk); | ||
| 812 | l2cap_chan_close(chan, 0); | 825 | l2cap_chan_close(chan, 0); |
| 826 | lock_sock(sk); | ||
| 813 | 827 | ||
| 814 | if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) | 828 | if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) |
| 815 | err = bt_sock_wait_state(sk, BT_CLOSED, | 829 | err = bt_sock_wait_state(sk, BT_CLOSED, |
| @@ -820,6 +834,11 @@ static int l2cap_sock_shutdown(struct socket *sock, int how) | |||
| 820 | err = -sk->sk_err; | 834 | err = -sk->sk_err; |
| 821 | 835 | ||
| 822 | release_sock(sk); | 836 | release_sock(sk); |
| 837 | l2cap_chan_unlock(chan); | ||
| 838 | |||
| 839 | if (conn) | ||
| 840 | mutex_unlock(&conn->chan_lock); | ||
| 841 | |||
| 823 | return err; | 842 | return err; |
| 824 | } | 843 | } |
| 825 | 844 | ||
| @@ -862,8 +881,12 @@ static int l2cap_sock_recv_cb(void *data, struct sk_buff *skb) | |||
| 862 | struct sock *sk = data; | 881 | struct sock *sk = data; |
| 863 | struct l2cap_pinfo *pi = l2cap_pi(sk); | 882 | struct l2cap_pinfo *pi = l2cap_pi(sk); |
| 864 | 883 | ||
| 865 | if (pi->rx_busy_skb) | 884 | lock_sock(sk); |
| 866 | return -ENOMEM; | 885 | |
| 886 | if (pi->rx_busy_skb) { | ||
| 887 | err = -ENOMEM; | ||
| 888 | goto done; | ||
| 889 | } | ||
| 867 | 890 | ||
| 868 | err = sock_queue_rcv_skb(sk, skb); | 891 | err = sock_queue_rcv_skb(sk, skb); |
| 869 | 892 | ||
| @@ -882,6 +905,9 @@ static int l2cap_sock_recv_cb(void *data, struct sk_buff *skb) | |||
| 882 | err = 0; | 905 | err = 0; |
| 883 | } | 906 | } |
| 884 | 907 | ||
| 908 | done: | ||
| 909 | release_sock(sk); | ||
| 910 | |||
| 885 | return err; | 911 | return err; |
| 886 | } | 912 | } |
| 887 | 913 | ||
| @@ -899,12 +925,22 @@ static void l2cap_sock_state_change_cb(void *data, int state) | |||
| 899 | sk->sk_state = state; | 925 | sk->sk_state = state; |
| 900 | } | 926 | } |
| 901 | 927 | ||
| 928 | static struct sk_buff *l2cap_sock_alloc_skb_cb(struct l2cap_chan *chan, | ||
| 929 | unsigned long len, int nb, | ||
| 930 | int *err) | ||
| 931 | { | ||
| 932 | struct sock *sk = chan->sk; | ||
| 933 | |||
| 934 | return bt_skb_send_alloc(sk, len, nb, err); | ||
| 935 | } | ||
| 936 | |||
| 902 | static struct l2cap_ops l2cap_chan_ops = { | 937 | static struct l2cap_ops l2cap_chan_ops = { |
| 903 | .name = "L2CAP Socket Interface", | 938 | .name = "L2CAP Socket Interface", |
| 904 | .new_connection = l2cap_sock_new_connection_cb, | 939 | .new_connection = l2cap_sock_new_connection_cb, |
| 905 | .recv = l2cap_sock_recv_cb, | 940 | .recv = l2cap_sock_recv_cb, |
| 906 | .close = l2cap_sock_close_cb, | 941 | .close = l2cap_sock_close_cb, |
| 907 | .state_change = l2cap_sock_state_change_cb, | 942 | .state_change = l2cap_sock_state_change_cb, |
| 943 | .alloc_skb = l2cap_sock_alloc_skb_cb, | ||
| 908 | }; | 944 | }; |
| 909 | 945 | ||
| 910 | static void l2cap_sock_destruct(struct sock *sk) | 946 | static void l2cap_sock_destruct(struct sock *sk) |
| @@ -1004,7 +1040,7 @@ static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int p | |||
| 1004 | INIT_LIST_HEAD(&bt_sk(sk)->accept_q); | 1040 | INIT_LIST_HEAD(&bt_sk(sk)->accept_q); |
| 1005 | 1041 | ||
| 1006 | sk->sk_destruct = l2cap_sock_destruct; | 1042 | sk->sk_destruct = l2cap_sock_destruct; |
| 1007 | sk->sk_sndtimeo = msecs_to_jiffies(L2CAP_CONN_TIMEOUT); | 1043 | sk->sk_sndtimeo = L2CAP_CONN_TIMEOUT; |
| 1008 | 1044 | ||
| 1009 | sock_reset_flag(sk, SOCK_ZAPPED); | 1045 | sock_reset_flag(sk, SOCK_ZAPPED); |
| 1010 | 1046 | ||
