RISC-V: Correctly print supported extensions
[platform/kernel/linux-starfive.git] / net / bluetooth / hci_sock.c
index eed0dd0..f1128c2 100644 (file)
@@ -59,6 +59,17 @@ struct hci_pinfo {
        char              comm[TASK_COMM_LEN];
 };
 
+static struct hci_dev *hci_hdev_from_sock(struct sock *sk)
+{
+       struct hci_dev *hdev = hci_pi(sk)->hdev;
+
+       if (!hdev)
+               return ERR_PTR(-EBADFD);
+       if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
+               return ERR_PTR(-EPIPE);
+       return hdev;
+}
+
 void hci_sock_set_flag(struct sock *sk, int nr)
 {
        set_bit(nr, &hci_pi(sk)->flags);
@@ -759,19 +770,13 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event)
        if (event == HCI_DEV_UNREG) {
                struct sock *sk;
 
-               /* Detach sockets from device */
+               /* Wake up sockets using this dead device */
                read_lock(&hci_sk_list.lock);
                sk_for_each(sk, &hci_sk_list.head) {
-                       lock_sock(sk);
                        if (hci_pi(sk)->hdev == hdev) {
-                               hci_pi(sk)->hdev = NULL;
                                sk->sk_err = EPIPE;
-                               sk->sk_state = BT_OPEN;
                                sk->sk_state_change(sk);
-
-                               hci_dev_put(hdev);
                        }
-                       release_sock(sk);
                }
                read_unlock(&hci_sk_list.lock);
        }
@@ -892,7 +897,7 @@ static int hci_sock_release(struct socket *sock)
        return 0;
 }
 
-static int hci_sock_blacklist_add(struct hci_dev *hdev, void __user *arg)
+static int hci_sock_reject_list_add(struct hci_dev *hdev, void __user *arg)
 {
        bdaddr_t bdaddr;
        int err;
@@ -902,14 +907,14 @@ static int hci_sock_blacklist_add(struct hci_dev *hdev, void __user *arg)
 
        hci_dev_lock(hdev);
 
-       err = hci_bdaddr_list_add(&hdev->blacklist, &bdaddr, BDADDR_BREDR);
+       err = hci_bdaddr_list_add(&hdev->reject_list, &bdaddr, BDADDR_BREDR);
 
        hci_dev_unlock(hdev);
 
        return err;
 }
 
-static int hci_sock_blacklist_del(struct hci_dev *hdev, void __user *arg)
+static int hci_sock_reject_list_del(struct hci_dev *hdev, void __user *arg)
 {
        bdaddr_t bdaddr;
        int err;
@@ -919,7 +924,7 @@ static int hci_sock_blacklist_del(struct hci_dev *hdev, void __user *arg)
 
        hci_dev_lock(hdev);
 
-       err = hci_bdaddr_list_del(&hdev->blacklist, &bdaddr, BDADDR_BREDR);
+       err = hci_bdaddr_list_del(&hdev->reject_list, &bdaddr, BDADDR_BREDR);
 
        hci_dev_unlock(hdev);
 
@@ -930,10 +935,10 @@ static int hci_sock_blacklist_del(struct hci_dev *hdev, void __user *arg)
 static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd,
                                unsigned long arg)
 {
-       struct hci_dev *hdev = hci_pi(sk)->hdev;
+       struct hci_dev *hdev = hci_hdev_from_sock(sk);
 
-       if (!hdev)
-               return -EBADFD;
+       if (IS_ERR(hdev))
+               return PTR_ERR(hdev);
 
        if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL))
                return -EBUSY;
@@ -959,12 +964,12 @@ static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd,
        case HCIBLOCKADDR:
                if (!capable(CAP_NET_ADMIN))
                        return -EPERM;
-               return hci_sock_blacklist_add(hdev, (void __user *)arg);
+               return hci_sock_reject_list_add(hdev, (void __user *)arg);
 
        case HCIUNBLOCKADDR:
                if (!capable(CAP_NET_ADMIN))
                        return -EPERM;
-               return hci_sock_blacklist_del(hdev, (void __user *)arg);
+               return hci_sock_reject_list_del(hdev, (void __user *)arg);
        }
 
        return -ENOIOCTLCMD;
@@ -1103,6 +1108,18 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr,
 
        lock_sock(sk);
 
+       /* Allow detaching from dead device and attaching to alive device, if
+        * the caller wants to re-bind (instead of close) this socket in
+        * response to hci_sock_dev_event(HCI_DEV_UNREG) notification.
+        */
+       hdev = hci_pi(sk)->hdev;
+       if (hdev && hci_dev_test_flag(hdev, HCI_UNREGISTER)) {
+               hci_pi(sk)->hdev = NULL;
+               sk->sk_state = BT_OPEN;
+               hci_dev_put(hdev);
+       }
+       hdev = NULL;
+
        if (sk->sk_state == BT_BOUND) {
                err = -EALREADY;
                goto done;
@@ -1130,7 +1147,7 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr,
                if (!hci_sock_gen_cookie(sk)) {
                        /* In the case when a cookie has already been assigned,
                         * then there has been already an ioctl issued against
-                        * an unbound socket and with that triggerd an open
+                        * an unbound socket and with that triggered an open
                         * notification. Send a close notification first to
                         * allow the state transition to bounded.
                         */
@@ -1326,9 +1343,9 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr,
                if (hci_pi(sk)->channel == HCI_CHANNEL_CONTROL) {
                        if (!hci_sock_gen_cookie(sk)) {
                                /* In the case when a cookie has already been
-                                * assigned, this socket will transtion from
+                                * assigned, this socket will transition from
                                 * a raw socket into a control socket. To
-                                * allow for a clean transtion, send the
+                                * allow for a clean transition, send the
                                 * close notification first.
                                 */
                                skb = create_monitor_ctrl_close(sk);
@@ -1379,9 +1396,9 @@ static int hci_sock_getname(struct socket *sock, struct sockaddr *addr,
 
        lock_sock(sk);
 
-       hdev = hci_pi(sk)->hdev;
-       if (!hdev) {
-               err = -EBADFD;
+       hdev = hci_hdev_from_sock(sk);
+       if (IS_ERR(hdev)) {
+               err = PTR_ERR(hdev);
                goto done;
        }
 
@@ -1743,9 +1760,9 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg,
                goto done;
        }
 
-       hdev = hci_pi(sk)->hdev;
-       if (!hdev) {
-               err = -EBADFD;
+       hdev = hci_hdev_from_sock(sk);
+       if (IS_ERR(hdev)) {
+               err = PTR_ERR(hdev);
                goto done;
        }