diff options
| author | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2012-03-21 11:26:18 +0400 | 
|---|---|---|
| committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2012-03-21 11:26:18 +0400 | 
| commit | 3d04d42312eacc68fbcddea337f7eb34bc035dfb (patch) | |
| tree | 7211df5704b743a7667159748c670a9744164482 /net/bluetooth/l2cap_sock.c | |
| parent | c98291ee1ceac03912e24b3219fa6e7dc0d52f5e (diff) | |
| parent | 69a7aebcf019ab3ff5764525ad6858fbe23bb86d (diff) | |
| download | linux-3d04d42312eacc68fbcddea337f7eb34bc035dfb.tar.xz | |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
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  	err = l2cap_chan_connect(chan, la.l2_psm, la.l2_cid, &la.l2_bdaddr);  	if (err) -		goto done; +		return err; + +	lock_sock(sk);  	err = bt_sock_wait_state(sk, BT_CONNECTED,  			sock_sndtimeo(sk, flags & O_NONBLOCK)); -done: -	if (sock_owned_by_user(sk)) -		release_sock(sk); + +	release_sock(sk); +  	return err;  } @@ -783,7 +785,7 @@ static void l2cap_sock_kill(struct sock *sk)  	if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)  		return; -	BT_DBG("sk %p state %d", sk, sk->sk_state); +	BT_DBG("sk %p state %s", sk, state_to_string(sk->sk_state));  	/* Kill poor orphan */ @@ -795,7 +797,8 @@ static void l2cap_sock_kill(struct sock *sk)  static int l2cap_sock_shutdown(struct socket *sock, int how)  {  	struct sock *sk = sock->sk; -	struct l2cap_chan *chan = l2cap_pi(sk)->chan; +	struct l2cap_chan *chan; +	struct l2cap_conn *conn;  	int err = 0;  	BT_DBG("sock %p, sk %p", sock, sk); @@ -803,13 +806,24 @@ static int l2cap_sock_shutdown(struct socket *sock, int how)  	if (!sk)  		return 0; +	chan = l2cap_pi(sk)->chan; +	conn = chan->conn; + +	if (conn) +		mutex_lock(&conn->chan_lock); + +	l2cap_chan_lock(chan);  	lock_sock(sk); +  	if (!sk->sk_shutdown) {  		if (chan->mode == L2CAP_MODE_ERTM)  			err = __l2cap_wait_ack(sk);  		sk->sk_shutdown = SHUTDOWN_MASK; + +		release_sock(sk);  		l2cap_chan_close(chan, 0); +		lock_sock(sk);  		if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)  			err = bt_sock_wait_state(sk, BT_CLOSED, @@ -820,6 +834,11 @@ static int l2cap_sock_shutdown(struct socket *sock, int how)  		err = -sk->sk_err;  	release_sock(sk); +	l2cap_chan_unlock(chan); + +	if (conn) +		mutex_unlock(&conn->chan_lock); +  	return err;  } @@ -862,8 +881,12 @@ static int l2cap_sock_recv_cb(void *data, struct sk_buff *skb)  	struct sock *sk = data;  	struct l2cap_pinfo *pi = l2cap_pi(sk); -	if (pi->rx_busy_skb) -		return -ENOMEM; +	lock_sock(sk); + +	if (pi->rx_busy_skb) { +		err = -ENOMEM; +		goto done; +	}  	err = sock_queue_rcv_skb(sk, skb); @@ -882,6 +905,9 @@ static int l2cap_sock_recv_cb(void *data, struct sk_buff *skb)  		err = 0;  	} +done: +	release_sock(sk); +  	return err;  } @@ -899,12 +925,22 @@ static void l2cap_sock_state_change_cb(void *data, int state)  	sk->sk_state = state;  } +static struct sk_buff *l2cap_sock_alloc_skb_cb(struct l2cap_chan *chan, +					       unsigned long len, int nb, +					       int *err) +{ +	struct sock *sk = chan->sk; + +	return bt_skb_send_alloc(sk, len, nb, err); +} +  static struct l2cap_ops l2cap_chan_ops = {  	.name		= "L2CAP Socket Interface",  	.new_connection	= l2cap_sock_new_connection_cb,  	.recv		= l2cap_sock_recv_cb,  	.close		= l2cap_sock_close_cb,  	.state_change	= l2cap_sock_state_change_cb, +	.alloc_skb	= l2cap_sock_alloc_skb_cb,  };  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  	INIT_LIST_HEAD(&bt_sk(sk)->accept_q);  	sk->sk_destruct = l2cap_sock_destruct; -	sk->sk_sndtimeo = msecs_to_jiffies(L2CAP_CONN_TIMEOUT); +	sk->sk_sndtimeo = L2CAP_CONN_TIMEOUT;  	sock_reset_flag(sk, SOCK_ZAPPED);  | 
