Bluetooth: l2cap: Fix lost wakeups waiting to accept socket
[firefly-linux-kernel-4.4.55.git] / net / bluetooth / l2cap_sock.c
index 5c36b3e8739cb706f9aa47e74a0ed9c5f72b8e24..7d713b1c4cbd59baac469e42ab6b53b4a05b23ba 100644 (file)
@@ -235,30 +235,26 @@ static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int fl
 
        lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
 
-       if (sk->sk_state != BT_LISTEN) {
-               err = -EBADFD;
-               goto done;
-       }
-
        timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
 
        BT_DBG("sk %p timeo %ld", sk, timeo);
 
        /* Wait for an incoming connection. (wake-one). */
        add_wait_queue_exclusive(sk_sleep(sk), &wait);
-       while (!(nsk = bt_accept_dequeue(sk, newsock))) {
+       while (1) {
                set_current_state(TASK_INTERRUPTIBLE);
-               if (!timeo) {
-                       err = -EAGAIN;
+
+               if (sk->sk_state != BT_LISTEN) {
+                       err = -EBADFD;
                        break;
                }
 
-               release_sock(sk);
-               timeo = schedule_timeout(timeo);
-               lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
+               nsk = bt_accept_dequeue(sk, newsock);
+               if (nsk)
+                       break;
 
-               if (sk->sk_state != BT_LISTEN) {
-                       err = -EBADFD;
+               if (!timeo) {
+                       err = -EAGAIN;
                        break;
                }
 
@@ -266,8 +262,12 @@ static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int fl
                        err = sock_intr_errno(timeo);
                        break;
                }
+
+               release_sock(sk);
+               timeo = schedule_timeout(timeo);
+               lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
        }
-       set_current_state(TASK_RUNNING);
+       __set_current_state(TASK_RUNNING);
        remove_wait_queue(sk_sleep(sk), &wait);
 
        if (err)