sk->sk_max_ack_backlog = backlog;
sk->sk_ack_backlog = 0;
+ /* Listening channels need to use nested locking in order not to
+ * cause lockdep warnings when the created child channels end up
+ * being locked in the same thread as the parent channel.
+ */
+ atomic_set(&chan->nesting, L2CAP_NESTING_PARENT);
+
chan->state = BT_LISTEN;
sk->sk_state = BT_LISTEN;
long timeo;
int err = 0;
- lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
+ lock_sock_nested(sk, L2CAP_NESTING_PARENT);
timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
release_sock(sk);
timeo = schedule_timeout(timeo);
- lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
+ lock_sock_nested(sk, L2CAP_NESTING_PARENT);
}
__set_current_state(TASK_RUNNING);
remove_wait_queue(sk_sleep(sk), &wait);
chan = l2cap_pi(sk)->chan;
conn = chan->conn;
+ BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
+
if (conn)
mutex_lock(&conn->chan_lock);
{
struct sock *sk;
- BT_DBG("parent %p", parent);
+ BT_DBG("parent %p state %s", parent,
+ state_to_string(parent->sk_state));
/* Close not yet accepted channels */
while ((sk = bt_accept_dequeue(parent, NULL))) {
struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+ BT_DBG("child chan %p state %s", chan,
+ state_to_string(chan->state));
+
l2cap_chan_lock(chan);
__clear_chan_timer(chan);
l2cap_chan_close(chan, ECONNRESET);
struct sock *sk = chan->data;
struct sock *parent;
- lock_sock(sk);
+ BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
+
+ /* This callback can be called both for server (BT_LISTEN)
+ * sockets as well as "normal" ones. To avoid lockdep warnings
+ * with child socket locking (through l2cap_sock_cleanup_listen)
+ * we need separation into separate nesting levels. The simplest
+ * way to accomplish this is to inherit the nesting level used
+ * for the channel.
+ */
+ lock_sock_nested(sk, atomic_read(&chan->nesting));
parent = bt_sk(sk)->parent;
static int l2cap_sock_memcpy_fromiovec_cb(struct l2cap_chan *chan,
unsigned char *kdata,
- struct iovec *iov, int len)
+ struct msghdr *msg, int len)
{
- return memcpy_fromiovec(kdata, iov, len);
+ return memcpy_from_msg(kdata, msg, len);
}
static void l2cap_sock_ready_cb(struct l2cap_chan *chan)