diff options
| author | Pauli Virtanen <pav@iki.fi> | 2026-04-12 21:47:42 +0300 |
|---|---|---|
| committer | Luiz Augusto von Dentz <luiz.von.dentz@intel.com> | 2026-05-06 22:58:29 +0300 |
| commit | b819db93d73f4593636299e229914052b89e3ef2 (patch) | |
| tree | 0fabf2cbbcbcf88da9db872b7f365e7bc773b8ea | |
| parent | b89e0100a5f6885f9748bbacc3f4e3bcff654e4c (diff) | |
| download | linux-b819db93d73f4593636299e229914052b89e3ef2.tar.xz | |
Bluetooth: SCO: fix sleeping under spinlock in sco_conn_ready
sco_conn_ready calls sleeping functions under conn->lock spinlock.
The critical section can be reduced: conn->hcon is modified only with
hdev->lock held. It is guaranteed to be held in sco_conn_ready, so
conn->lock is not needed to guard it.
Move taking conn->lock after lock_sock(parent). This also follows the
lock ordering lock_sock() > conn->lock elsewhere in the file.
Fixes: 27c24fda62b60 ("Bluetooth: switch to lock_sock in SCO")
Signed-off-by: Pauli Virtanen <pav@iki.fi>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
| -rw-r--r-- | net/bluetooth/sco.c | 20 |
1 files changed, 9 insertions, 11 deletions
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 18826d4b9c0b..3a5479538e85 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -1377,26 +1377,24 @@ static void sco_conn_ready(struct sco_conn *conn) sk->sk_state_change(sk); release_sock(sk); } else { - sco_conn_lock(conn); - - if (!conn->hcon) { - sco_conn_unlock(conn); + if (!conn->hcon) return; - } + + lockdep_assert_held(&conn->hcon->hdev->lock); parent = sco_get_sock_listen(&conn->hcon->src); - if (!parent) { - sco_conn_unlock(conn); + if (!parent) return; - } lock_sock(parent); + sco_conn_lock(conn); + sk = sco_sock_alloc(sock_net(parent), NULL, BTPROTO_SCO, GFP_ATOMIC, 0); if (!sk) { - release_sock(parent); sco_conn_unlock(conn); + release_sock(parent); return; } @@ -1417,9 +1415,9 @@ static void sco_conn_ready(struct sco_conn *conn) /* Wake up parent */ parent->sk_data_ready(parent); - release_sock(parent); - sco_conn_unlock(conn); + + release_sock(parent); } } |
