diff options
author | Iulia Tanasescu <iulia.tanasescu@nxp.com> | 2024-11-11 13:47:08 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2024-12-05 14:01:59 +0100 |
commit | 1360e5b6ce63d63d23223a659ca2bbafa30a53aa (patch) | |
tree | b3047665505f73ec58e9e23f47203083e1b3c835 | |
parent | 91d19383b7ed035e22165ae5c836e50bb9f95fbe (diff) |
Bluetooth: ISO: Send BIG Create Sync via hci_sync
[ Upstream commit 07a9342b94a91b306ed1cf6aa8254aea210764c9 ]
Before issuing the LE BIG Create Sync command, an available BIG handle
is chosen by iterating through the conn_hash list and finding the first
unused value.
If a BIG is terminated, the associated hcons are removed from the list
and the LE BIG Terminate Sync command is sent via hci_sync queue.
However, a new LE BIG Create sync command might be issued via
hci_send_cmd, before the previous BIG sync was terminated. This
can cause the same BIG handle to be reused and the LE BIG Create Sync
to fail with Command Disallowed.
< HCI Command: LE Broadcast Isochronous Group Create Sync (0x08|0x006b)
BIG Handle: 0x00
BIG Sync Handle: 0x0002
Encryption: Unencrypted (0x00)
Broadcast Code[16]: 00000000000000000000000000000000
Maximum Number Subevents: 0x00
Timeout: 20000 ms (0x07d0)
Number of BIS: 1
BIS ID: 0x01
> HCI Event: Command Status (0x0f) plen 4
LE Broadcast Isochronous Group Create Sync (0x08|0x006b) ncmd 1
Status: Command Disallowed (0x0c)
< HCI Command: LE Broadcast Isochronous Group Terminate Sync (0x08|0x006c)
BIG Handle: 0x00
This commit fixes the ordering of the LE BIG Create Sync/LE BIG Terminate
Sync commands, to make sure that either the previous BIG sync is
terminated before reusing the handle, or that a new handle is chosen
for a new sync.
Fixes: eca0ae4aea66 ("Bluetooth: Add initial implementation of BIS connections")
Signed-off-by: Iulia Tanasescu <iulia.tanasescu@nxp.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r-- | net/bluetooth/hci_conn.c | 17 | ||||
-rw-r--r-- | net/bluetooth/iso.c | 9 |
2 files changed, 25 insertions, 1 deletions
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 1ff62bf9d41b..6354cdf9c2b3 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -2188,7 +2188,15 @@ static bool hci_conn_check_create_big_sync(struct hci_conn *conn) return true; } -int hci_le_big_create_sync_pending(struct hci_dev *hdev) +static void big_create_sync_complete(struct hci_dev *hdev, void *data, int err) +{ + bt_dev_dbg(hdev, ""); + + if (err) + bt_dev_err(hdev, "Unable to create BIG sync: %d", err); +} + +static int big_create_sync(struct hci_dev *hdev, void *data) { DEFINE_FLEX(struct hci_cp_le_big_create_sync, pdu, bis, num_bis, 0x11); struct hci_conn *conn; @@ -2245,6 +2253,13 @@ unlock: struct_size(pdu, bis, pdu->num_bis), pdu); } +int hci_le_big_create_sync_pending(struct hci_dev *hdev) +{ + /* Queue big_create_sync */ + return hci_cmd_sync_queue_once(hdev, big_create_sync, + NULL, big_create_sync_complete); +} + int hci_le_big_create_sync(struct hci_dev *hdev, struct hci_conn *hcon, struct bt_iso_qos *qos, __u16 sync_handle, __u8 num_bis, __u8 bis[]) diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c index 463c61712b24..5e2d9758bd3c 100644 --- a/net/bluetooth/iso.c +++ b/net/bluetooth/iso.c @@ -1392,6 +1392,13 @@ static void iso_conn_big_sync(struct sock *sk) if (!hdev) return; + /* hci_le_big_create_sync requires hdev lock to be held, since + * it enqueues the HCI LE BIG Create Sync command via + * hci_cmd_sync_queue_once, which checks hdev flags that might + * change. + */ + hci_dev_lock(hdev); + if (!test_and_set_bit(BT_SK_BIG_SYNC, &iso_pi(sk)->flags)) { err = hci_le_big_create_sync(hdev, iso_pi(sk)->conn->hcon, &iso_pi(sk)->qos, @@ -1402,6 +1409,8 @@ static void iso_conn_big_sync(struct sock *sk) bt_dev_err(hdev, "hci_le_big_create_sync: %d", err); } + + hci_dev_unlock(hdev); } static int iso_sock_recvmsg(struct socket *sock, struct msghdr *msg, |