@@ -764,12 +764,9 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event)
sk_for_each(sk, &hci_sk_list.head) {
bh_lock_sock_nested(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);
}
bh_unlock_sock(sk);
}
@@ -880,6 +877,7 @@ static int hci_sock_release(struct socket *sock)
atomic_dec(&hdev->promisc);
hci_dev_put(hdev);
+ hci_pi(sk)->hdev = NULL;
}
sock_orphan(sk);
@@ -1727,10 +1725,10 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg,
break;
case HCI_CHANNEL_MONITOR:
err = -EOPNOTSUPP;
- goto done;
+ goto donefast;
case HCI_CHANNEL_LOGGING:
err = hci_logging_frame(sk, msg, len);
- goto done;
+ goto donefast;
default:
mutex_lock(&mgmt_chan_list_lock);
chan = __hci_mgmt_chan_find(hci_pi(sk)->channel);
@@ -1740,15 +1738,16 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg,
err = -EINVAL;
mutex_unlock(&mgmt_chan_list_lock);
- goto done;
+ goto donefast;
}
hdev = hci_pi(sk)->hdev;
if (!hdev) {
err = -EBADFD;
- goto done;
+ goto donefast;
}
+ hci_dev_lock(hdev);
if (!test_bit(HCI_UP, &hdev->flags)) {
err = -ENETDOWN;
goto done;
@@ -1832,6 +1831,8 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg,
err = len;
done:
+ hci_dev_unlock(hdev);
+donefast:
release_sock(sk);
return err;