Commit 6be36555 authored by Andrei Emeltchenko's avatar Andrei Emeltchenko Committed by Johan Hedberg
Browse files

Bluetooth: Change sk lock to chan lock in L2CAP core



Change sk lock to chan lock in l2cap core and move sk locks
to l2cap sock code. bh_locks were used because of being RCU
critical section. When needed use explicit socket locks.

Signed-off-by: default avatarAndrei Emeltchenko <andrei.emeltchenko@intel.com>
Reviewed-by: default avatarUlisses Furquim <ulisses@profusion.mobi>
Acked-by: default avatarGustavo F. Padovan <padovan@profusion.mobi>
Signed-off-by: default avatarJohan Hedberg <johan.hedberg@intel.com>
parent 643162a8
Loading
Loading
Loading
Loading
+98 −68
Original line number Diff line number Diff line
@@ -238,13 +238,12 @@ static void l2cap_chan_timeout(struct work_struct *work)
	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
							chan_timer.work);
	struct l2cap_conn *conn = chan->conn;
	struct sock *sk = chan->sk;
	int reason;

	BT_DBG("chan %p state %s", chan, state_to_string(chan->state));

	mutex_lock(&conn->chan_lock);
	lock_sock(sk);
	l2cap_chan_lock(chan);

	if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
		reason = ECONNREFUSED;
@@ -256,7 +255,7 @@ static void l2cap_chan_timeout(struct work_struct *work)

	l2cap_chan_close(chan, reason);

	release_sock(sk);
	l2cap_chan_unlock(chan);

	chan->ops->close(chan->data);
	mutex_unlock(&conn->chan_lock);
@@ -356,8 +355,6 @@ void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
	mutex_unlock(&conn->chan_lock);
}

/* Delete channel.
 * Must be called on the locked socket. */
static void l2cap_chan_del(struct l2cap_chan *chan, int err)
{
	struct sock *sk = chan->sk;
@@ -378,6 +375,8 @@ static void l2cap_chan_del(struct l2cap_chan *chan, int err)
		hci_conn_put(conn->hcon);
	}

	lock_sock(sk);

	__l2cap_state_change(chan, BT_CLOSED);
	sock_set_flag(sk, SOCK_ZAPPED);

@@ -390,6 +389,8 @@ static void l2cap_chan_del(struct l2cap_chan *chan, int err)
	} else
		sk->sk_state_change(sk);

	release_sock(sk);

	if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) &&
			test_bit(CONF_INPUT_DONE, &chan->conf_state)))
		return;
@@ -422,10 +423,10 @@ static void l2cap_chan_cleanup_listen(struct sock *parent)
	while ((sk = bt_accept_dequeue(parent, NULL))) {
		struct l2cap_chan *chan = l2cap_pi(sk)->chan;

		l2cap_chan_lock(chan);
		__clear_chan_timer(chan);
		lock_sock(sk);
		l2cap_chan_close(chan, ECONNRESET);
		release_sock(sk);
		l2cap_chan_unlock(chan);

		chan->ops->close(chan->data);
	}
@@ -441,10 +442,12 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason)

	switch (chan->state) {
	case BT_LISTEN:
		lock_sock(sk);
		l2cap_chan_cleanup_listen(sk);

		__l2cap_state_change(chan, BT_CLOSED);
		sock_set_flag(sk, SOCK_ZAPPED);
		release_sock(sk);
		break;

	case BT_CONNECTED:
@@ -487,7 +490,9 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason)
		break;

	default:
		lock_sock(sk);
		sock_set_flag(sk, SOCK_ZAPPED);
		release_sock(sk);
		break;
	}
}
@@ -715,6 +720,7 @@ static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)

static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
{
	struct sock *sk = chan->sk;
	struct l2cap_disconn_req req;

	if (!conn)
@@ -731,8 +737,10 @@ static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *c
	l2cap_send_cmd(conn, l2cap_get_ident(conn),
			L2CAP_DISCONN_REQ, sizeof(req), &req);

	lock_sock(sk);
	__l2cap_state_change(chan, BT_DISCONN);
	__l2cap_chan_set_err(chan, err);
	release_sock(sk);
}

/* ---- L2CAP connections ---- */
@@ -747,10 +755,10 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
	list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
		struct sock *sk = chan->sk;

		bh_lock_sock(sk);
		l2cap_chan_lock(chan);

		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
			bh_unlock_sock(sk);
			l2cap_chan_unlock(chan);
			continue;
		}

@@ -759,17 +767,15 @@ static void l2cap_conn_start(struct l2cap_conn *conn)

			if (!l2cap_chan_check_security(chan) ||
					!__l2cap_no_conn_pending(chan)) {
				bh_unlock_sock(sk);
				l2cap_chan_unlock(chan);
				continue;
			}

			if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
					&& test_bit(CONF_STATE2_DEVICE,
					&chan->conf_state)) {
				/* l2cap_chan_close() calls list_del(chan)
				 * so release the lock */
				l2cap_chan_close(chan, ECONNRESET);
				bh_unlock_sock(sk);
				l2cap_chan_unlock(chan);
				continue;
			}

@@ -789,6 +795,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
			rsp.dcid = cpu_to_le16(chan->scid);

			if (l2cap_chan_check_security(chan)) {
				lock_sock(sk);
				if (bt_sk(sk)->defer_setup) {
					struct sock *parent = bt_sk(sk)->parent;
					rsp.result = cpu_to_le16(L2CAP_CR_PEND);
@@ -801,6 +808,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
					rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
					rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
				}
				release_sock(sk);
			} else {
				rsp.result = cpu_to_le16(L2CAP_CR_PEND);
				rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
@@ -811,7 +819,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)

			if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
					rsp.result != L2CAP_CR_SUCCESS) {
				bh_unlock_sock(sk);
				l2cap_chan_unlock(chan);
				continue;
			}

@@ -821,7 +829,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
			chan->num_conf_req++;
		}

		bh_unlock_sock(sk);
		l2cap_chan_unlock(chan);
	}

	mutex_unlock(&conn->chan_lock);
@@ -910,7 +918,11 @@ clean:
static void l2cap_chan_ready(struct l2cap_chan *chan)
{
	struct sock *sk = chan->sk;
	struct sock *parent = bt_sk(sk)->parent;
	struct sock *parent;

	lock_sock(sk);

	parent = bt_sk(sk)->parent;

	BT_DBG("sk %p, parent %p", sk, parent);

@@ -922,6 +934,8 @@ static void l2cap_chan_ready(struct l2cap_chan *chan)

	if (parent)
		parent->sk_data_ready(parent, 0);

	release_sock(sk);
}

static void l2cap_conn_ready(struct l2cap_conn *conn)
@@ -939,23 +953,25 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
	mutex_lock(&conn->chan_lock);

	list_for_each_entry(chan, &conn->chan_l, list) {
		struct sock *sk = chan->sk;

		bh_lock_sock(sk);
		l2cap_chan_lock(chan);

		if (conn->hcon->type == LE_LINK) {
			if (smp_conn_security(conn, chan->sec_level))
				l2cap_chan_ready(chan);

		} else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
			struct sock *sk = chan->sk;
			__clear_chan_timer(chan);
			lock_sock(sk);
			__l2cap_state_change(chan, BT_CONNECTED);
			sk->sk_state_change(sk);
			release_sock(sk);

		} else if (chan->state == BT_CONNECT)
			l2cap_do_start(chan);

		bh_unlock_sock(sk);
		l2cap_chan_unlock(chan);
	}

	mutex_unlock(&conn->chan_lock);
@@ -993,7 +1009,6 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
{
	struct l2cap_conn *conn = hcon->l2cap_data;
	struct l2cap_chan *chan, *l;
	struct sock *sk;

	if (!conn)
		return;
@@ -1006,10 +1021,12 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)

	/* Kill channels */
	list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
		sk = chan->sk;
		lock_sock(sk);
		l2cap_chan_lock(chan);

		l2cap_chan_del(chan, err);
		release_sock(sk);

		l2cap_chan_unlock(chan);

		chan->ops->close(chan->data);
	}

@@ -1140,7 +1157,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *d

	hci_dev_lock(hdev);

	lock_sock(sk);
	l2cap_chan_lock(chan);

	/* PSM must be odd and lsb of upper byte must be 0 */
	if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid &&
@@ -1167,17 +1184,21 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *d
		goto done;
	}

	lock_sock(sk);

	switch (sk->sk_state) {
	case BT_CONNECT:
	case BT_CONNECT2:
	case BT_CONFIG:
		/* Already connecting */
		err = 0;
		release_sock(sk);
		goto done;

	case BT_CONNECTED:
		/* Already connected */
		err = -EISCONN;
		release_sock(sk);
		goto done;

	case BT_OPEN:
@@ -1187,11 +1208,15 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *d

	default:
		err = -EBADFD;
		release_sock(sk);
		goto done;
	}

	/* Set destination address and psm */
	bacpy(&bt_sk(sk)->dst, dst);

	release_sock(sk);

	chan->psm = psm;
	chan->dcid = cid;

@@ -1219,16 +1244,18 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *d
	/* Update source addr of the socket */
	bacpy(src, conn->src);

	l2cap_chan_unlock(chan);
	l2cap_chan_add(conn, chan);
	l2cap_chan_lock(chan);

	__l2cap_state_change(chan, BT_CONNECT);
	l2cap_state_change(chan, BT_CONNECT);
	__set_chan_timer(chan, sk->sk_sndtimeo);

	if (hcon->state == BT_CONNECTED) {
		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
			__clear_chan_timer(chan);
			if (l2cap_chan_check_security(chan))
				__l2cap_state_change(chan, BT_CONNECTED);
				l2cap_state_change(chan, BT_CONNECTED);
		} else
			l2cap_do_start(chan);
	}
@@ -1236,6 +1263,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *d
	err = 0;

done:
	l2cap_chan_unlock(chan);
	hci_dev_unlock(hdev);
	hci_dev_put(hdev);
	return err;
@@ -1277,14 +1305,14 @@ static void l2cap_monitor_timeout(struct work_struct *work)
{
	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
							monitor_timer.work);
	struct sock *sk = chan->sk;

	BT_DBG("chan %p", chan);

	lock_sock(sk);
	l2cap_chan_lock(chan);

	if (chan->retry_count >= chan->remote_max_tx) {
		l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
		release_sock(sk);
		l2cap_chan_unlock(chan);
		return;
	}

@@ -1292,25 +1320,26 @@ static void l2cap_monitor_timeout(struct work_struct *work)
	__set_monitor_timer(chan);

	l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
	release_sock(sk);
	l2cap_chan_unlock(chan);
}

static void l2cap_retrans_timeout(struct work_struct *work)
{
	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
							retrans_timer.work);
	struct sock *sk = chan->sk;

	BT_DBG("chan %p", chan);

	lock_sock(sk);
	l2cap_chan_lock(chan);

	chan->retry_count = 1;
	__set_monitor_timer(chan);

	set_bit(CONN_WAIT_F, &chan->conn_state);

	l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
	release_sock(sk);

	l2cap_chan_unlock(chan);
}

static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
@@ -2001,9 +2030,11 @@ static void l2cap_ack_timeout(struct work_struct *work)

	BT_DBG("chan %p", chan);

	lock_sock(chan->sk);
	l2cap_chan_lock(chan);

	__l2cap_send_ack(chan);
	release_sock(chan->sk);

	l2cap_chan_unlock(chan);

	l2cap_chan_put(chan);
}
@@ -2664,7 +2695,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd

	bt_accept_enqueue(parent, sk);

	l2cap_chan_add(conn, chan);
	__l2cap_chan_add(conn, chan);

	dcid = chan->scid;

@@ -2737,7 +2768,6 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
	struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
	u16 scid, dcid, result, status;
	struct l2cap_chan *chan;
	struct sock *sk;
	u8 req[128];
	int err;

@@ -2767,8 +2797,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd

	err = 0;

	sk = chan->sk;
	lock_sock(sk);
	l2cap_chan_lock(chan);

	switch (result) {
	case L2CAP_CR_SUCCESS:
@@ -2794,7 +2823,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
		break;
	}

	release_sock(sk);
	l2cap_chan_unlock(chan);

unlock:
	mutex_unlock(&conn->chan_lock);
@@ -2819,7 +2848,6 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
	u16 dcid, flags;
	u8 rsp[64];
	struct l2cap_chan *chan;
	struct sock *sk;
	int len;

	dcid  = __le16_to_cpu(req->dcid);
@@ -2831,8 +2859,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
	if (!chan)
		return -ENOENT;

	sk = chan->sk;
	lock_sock(sk);
	l2cap_chan_lock(chan);

	if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
		struct l2cap_cmd_rej_cid rej;
@@ -2921,7 +2948,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
	}

unlock:
	release_sock(sk);
	l2cap_chan_unlock(chan);
	return 0;
}

@@ -2930,7 +2957,6 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
	struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
	u16 scid, flags, result;
	struct l2cap_chan *chan;
	struct sock *sk;
	int len = cmd->len - sizeof(*rsp);

	scid   = __le16_to_cpu(rsp->scid);
@@ -2944,8 +2970,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
	if (!chan)
		return 0;

	sk = chan->sk;
	lock_sock(sk);
	l2cap_chan_lock(chan);

	switch (result) {
	case L2CAP_CONF_SUCCESS:
@@ -3004,7 +3029,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
		}

	default:
		__l2cap_chan_set_err(chan, ECONNRESET);
		l2cap_chan_set_err(chan, ECONNRESET);

		__set_chan_timer(chan,
				msecs_to_jiffies(L2CAP_DISC_REJ_TIMEOUT));
@@ -3031,7 +3056,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
	}

done:
	release_sock(sk);
	l2cap_chan_unlock(chan);
	return 0;
}

@@ -3056,17 +3081,21 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
		return 0;
	}

	l2cap_chan_lock(chan);

	sk = chan->sk;
	lock_sock(sk);

	rsp.dcid = cpu_to_le16(chan->scid);
	rsp.scid = cpu_to_le16(chan->dcid);
	l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);

	lock_sock(sk);
	sk->sk_shutdown = SHUTDOWN_MASK;
	release_sock(sk);

	l2cap_chan_del(chan, ECONNRESET);
	release_sock(sk);

	l2cap_chan_unlock(chan);

	chan->ops->close(chan->data);

@@ -3080,7 +3109,6 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
	struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
	u16 dcid, scid;
	struct l2cap_chan *chan;
	struct sock *sk;

	scid = __le16_to_cpu(rsp->scid);
	dcid = __le16_to_cpu(rsp->dcid);
@@ -3095,11 +3123,11 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
		return 0;
	}

	sk = chan->sk;
	lock_sock(sk);
	l2cap_chan_lock(chan);

	l2cap_chan_del(chan, 0);
	release_sock(sk);

	l2cap_chan_unlock(chan);

	chan->ops->close(chan->data);

@@ -4251,7 +4279,6 @@ drop:
static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
{
	struct l2cap_chan *chan;
	struct sock *sk = NULL;
	u32 control;
	u16 tx_seq;
	int len;
@@ -4259,11 +4286,12 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
	chan = l2cap_get_chan_by_scid(conn, cid);
	if (!chan) {
		BT_DBG("unknown cid 0x%4.4x", cid);
		goto drop;
		/* Drop packet and return */
		kfree(skb);
		return 0;
	}

	sk = chan->sk;
	lock_sock(sk);
	l2cap_chan_lock(chan);

	BT_DBG("chan %p, len %d", chan, skb->len);

@@ -4334,8 +4362,7 @@ drop:
	kfree_skb(skb);

done:
	if (sk)
		release_sock(sk);
	l2cap_chan_unlock(chan);

	return 0;
}
@@ -4554,9 +4581,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
	mutex_lock(&conn->chan_lock);

	list_for_each_entry(chan, &conn->chan_l, list) {
		struct sock *sk = chan->sk;

		bh_lock_sock(sk);
		l2cap_chan_lock(chan);

		BT_DBG("chan->scid %d", chan->scid);

@@ -4566,19 +4591,19 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
				l2cap_chan_ready(chan);
			}

			bh_unlock_sock(sk);
			l2cap_chan_unlock(chan);
			continue;
		}

		if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
			bh_unlock_sock(sk);
			l2cap_chan_unlock(chan);
			continue;
		}

		if (!status && (chan->state == BT_CONNECTED ||
						chan->state == BT_CONFIG)) {
			l2cap_check_encryption(chan, encrypt);
			bh_unlock_sock(sk);
			l2cap_chan_unlock(chan);
			continue;
		}

@@ -4599,9 +4624,12 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
					msecs_to_jiffies(L2CAP_DISC_TIMEOUT));
			}
		} else if (chan->state == BT_CONNECT2) {
			struct sock *sk = chan->sk;
			struct l2cap_conn_rsp rsp;
			__u16 res, stat;

			lock_sock(sk);

			if (!status) {
				if (bt_sk(sk)->defer_setup) {
					struct sock *parent = bt_sk(sk)->parent;
@@ -4622,6 +4650,8 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
				stat = L2CAP_CS_NO_INFO;
			}

			release_sock(sk);

			rsp.scid   = cpu_to_le16(chan->dcid);
			rsp.dcid   = cpu_to_le16(chan->scid);
			rsp.result = cpu_to_le16(res);
@@ -4630,7 +4660,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
							sizeof(rsp), &rsp);
		}

		bh_unlock_sock(sk);
		l2cap_chan_unlock(chan);
	}

	mutex_unlock(&conn->chan_lock);
+16 −2
Original line number Diff line number Diff line
@@ -127,6 +127,8 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
	if (err)
		goto done;

	lock_sock(sk);

	err = bt_sock_wait_state(sk, BT_CONNECTED,
			sock_sndtimeo(sk, flags & O_NONBLOCK));
done:
@@ -810,14 +812,18 @@ static int l2cap_sock_shutdown(struct socket *sock, int how)
	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,
@@ -828,6 +834,7 @@ 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);
@@ -874,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);

@@ -894,6 +905,9 @@ static int l2cap_sock_recv_cb(void *data, struct sk_buff *skb)
		err = 0;
	}

done:
	release_sock(sk);

	return err;
}