Skip to content

Commit 37d04ae

Browse files
pvVudentz
authored andcommitted
Bluetooth: ISO: do not emit new LE Create CIS if previous is pending
LE Create CIS command shall not be sent before all CIS Established events from its previous invocation have been processed. Currently it is sent via hci_sync but that only waits for the first event, but there can be multiple. Make it wait for all events, and simplify the CIS creation as follows: Add new flag HCI_CONN_CREATE_CIS, which is set if Create CIS has been sent for the connection but it is not yet completed. Make BT_CONNECT state to mean the connection wants Create CIS. On events after which new Create CIS may need to be sent, send it if possible and some connections need it. These events are: hci_connect_cis, iso_connect_cfm, hci_cs_le_create_cis, hci_le_cis_estabilished_evt. The Create CIS status/completion events shall queue new Create CIS only if at least one of the connections transitions away from BT_CONNECT, so that we don't loop if controller is sending bogus events. This fixes sending multiple CIS Create for the same CIS in the "ISO AC 6(i) - Success" BlueZ test case: < HCI Command: LE Create Co.. (0x08|0x0064) plen 9 torvalds#129 [hci0] Number of CIS: 2 CIS Handle: 257 ACL Handle: 42 CIS Handle: 258 ACL Handle: 42 > HCI Event: Command Status (0x0f) plen 4 torvalds#130 [hci0] LE Create Connected Isochronous Stream (0x08|0x0064) ncmd 1 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 29 torvalds#131 [hci0] LE Connected Isochronous Stream Established (0x19) Status: Success (0x00) Connection Handle: 257 ... < HCI Command: LE Setup Is.. (0x08|0x006e) plen 13 torvalds#132 [hci0] ... > HCI Event: Command Complete (0x0e) plen 6 torvalds#133 [hci0] LE Setup Isochronous Data Path (0x08|0x006e) ncmd 1 ... < HCI Command: LE Create Co.. (0x08|0x0064) plen 5 torvalds#134 [hci0] Number of CIS: 1 CIS Handle: 258 ACL Handle: 42 > HCI Event: Command Status (0x0f) plen 4 torvalds#135 [hci0] LE Create Connected Isochronous Stream (0x08|0x0064) ncmd 1 Status: ACL Connection Already Exists (0x0b) > HCI Event: LE Meta Event (0x3e) plen 29 torvalds#136 [hci0] LE Connected Isochronous Stream Established (0x19) Status: Success (0x00) Connection Handle: 258 ... Fixes: c09b80b ("Bluetooth: hci_conn: Fix not waiting for HCI_EVT_LE_CIS_ESTABLISHED") Signed-off-by: Pauli Virtanen <pav@iki.fi> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
1 parent 20b3370 commit 37d04ae

File tree

6 files changed

+119
-78
lines changed

6 files changed

+119
-78
lines changed

include/net/bluetooth/hci_core.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,7 @@ enum {
976976
HCI_CONN_AUTH_FAILURE,
977977
HCI_CONN_PER_ADV,
978978
HCI_CONN_BIG_CREATED,
979+
HCI_CONN_CREATE_CIS,
979980
};
980981

981982
static inline bool hci_conn_ssp_enabled(struct hci_conn *conn)
@@ -1352,7 +1353,8 @@ int hci_disconnect(struct hci_conn *conn, __u8 reason);
13521353
bool hci_setup_sync(struct hci_conn *conn, __u16 handle);
13531354
void hci_sco_setup(struct hci_conn *conn, __u8 status);
13541355
bool hci_iso_setup_path(struct hci_conn *conn);
1355-
int hci_le_create_cis(struct hci_conn *conn);
1356+
int hci_le_create_cis_pending(struct hci_dev *hdev);
1357+
int hci_conn_check_create_cis(struct hci_conn *conn);
13561358

13571359
struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
13581360
u8 role);

include/net/bluetooth/hci_sync.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ int hci_abort_conn_sync(struct hci_dev *hdev, struct hci_conn *conn, u8 reason);
124124

125125
int hci_le_create_conn_sync(struct hci_dev *hdev, struct hci_conn *conn);
126126

127-
int hci_le_create_cis_sync(struct hci_dev *hdev, struct hci_conn *conn);
127+
int hci_le_create_cis_sync(struct hci_dev *hdev);
128128

129129
int hci_le_remove_cig_sync(struct hci_dev *hdev, u8 handle);
130130

net/bluetooth/hci_conn.c

+30-44
Original file line numberDiff line numberDiff line change
@@ -1992,59 +1992,47 @@ bool hci_iso_setup_path(struct hci_conn *conn)
19921992
return true;
19931993
}
19941994

1995-
static int hci_create_cis_sync(struct hci_dev *hdev, void *data)
1995+
int hci_conn_check_create_cis(struct hci_conn *conn)
19961996
{
1997-
return hci_le_create_cis_sync(hdev, data);
1998-
}
1997+
if (conn->type != ISO_LINK || !bacmp(&conn->dst, BDADDR_ANY))
1998+
return -EINVAL;
19991999

2000-
int hci_le_create_cis(struct hci_conn *conn)
2001-
{
2002-
struct hci_conn *cis;
2003-
struct hci_link *link, *t;
2004-
struct hci_dev *hdev = conn->hdev;
2005-
int err;
2000+
if (!conn->parent || conn->parent->state != BT_CONNECTED ||
2001+
conn->state != BT_CONNECT || conn->handle == HCI_CONN_HANDLE_UNSET)
2002+
return 1;
20062003

2007-
bt_dev_dbg(hdev, "hcon %p", conn);
2004+
return 0;
2005+
}
20082006

2009-
switch (conn->type) {
2010-
case LE_LINK:
2011-
if (conn->state != BT_CONNECTED || list_empty(&conn->link_list))
2012-
return -EINVAL;
2007+
static int hci_create_cis_sync(struct hci_dev *hdev, void *data)
2008+
{
2009+
return hci_le_create_cis_sync(hdev);
2010+
}
20132011

2014-
cis = NULL;
2012+
int hci_le_create_cis_pending(struct hci_dev *hdev)
2013+
{
2014+
struct hci_conn *conn;
2015+
bool pending = false;
20152016

2016-
/* hci_conn_link uses list_add_tail_rcu so the list is in
2017-
* the same order as the connections are requested.
2018-
*/
2019-
list_for_each_entry_safe(link, t, &conn->link_list, list) {
2020-
if (link->conn->state == BT_BOUND) {
2021-
err = hci_le_create_cis(link->conn);
2022-
if (err)
2023-
return err;
2017+
rcu_read_lock();
20242018

2025-
cis = link->conn;
2026-
}
2019+
list_for_each_entry_rcu(conn, &hdev->conn_hash.list, list) {
2020+
if (test_bit(HCI_CONN_CREATE_CIS, &conn->flags)) {
2021+
rcu_read_unlock();
2022+
return -EBUSY;
20272023
}
20282024

2029-
return cis ? 0 : -EINVAL;
2030-
case ISO_LINK:
2031-
cis = conn;
2032-
break;
2033-
default:
2034-
return -EINVAL;
2025+
if (!hci_conn_check_create_cis(conn))
2026+
pending = true;
20352027
}
20362028

2037-
if (cis->state == BT_CONNECT)
2029+
rcu_read_unlock();
2030+
2031+
if (!pending)
20382032
return 0;
20392033

20402034
/* Queue Create CIS */
2041-
err = hci_cmd_sync_queue(hdev, hci_create_cis_sync, cis, NULL);
2042-
if (err)
2043-
return err;
2044-
2045-
cis->state = BT_CONNECT;
2046-
2047-
return 0;
2035+
return hci_cmd_sync_queue(hdev, hci_create_cis_sync, NULL, NULL);
20482036
}
20492037

20502038
static void hci_iso_qos_setup(struct hci_dev *hdev, struct hci_conn *conn,
@@ -2319,11 +2307,9 @@ struct hci_conn *hci_connect_cis(struct hci_dev *hdev, bdaddr_t *dst,
23192307
return NULL;
23202308
}
23212309

2322-
/* If LE is already connected and CIS handle is already set proceed to
2323-
* Create CIS immediately.
2324-
*/
2325-
if (le->state == BT_CONNECTED && cis->handle != HCI_CONN_HANDLE_UNSET)
2326-
hci_le_create_cis(cis);
2310+
cis->state = BT_CONNECT;
2311+
2312+
hci_le_create_cis_pending(hdev);
23272313

23282314
return cis;
23292315
}

net/bluetooth/hci_event.c

+21-4
Original file line numberDiff line numberDiff line change
@@ -3807,6 +3807,7 @@ static u8 hci_cc_le_set_cig_params(struct hci_dev *hdev, void *data,
38073807
struct hci_cp_le_set_cig_params *cp;
38083808
struct hci_conn *conn;
38093809
u8 status = rp->status;
3810+
bool pending = false;
38103811
int i;
38113812

38123813
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
@@ -3848,13 +3849,15 @@ static u8 hci_cc_le_set_cig_params(struct hci_dev *hdev, void *data,
38483849

38493850
bt_dev_dbg(hdev, "%p handle 0x%4.4x parent %p", conn,
38503851
conn->handle, conn->parent);
3851-
3852-
/* Create CIS if LE is already connected */
3853-
if (conn->parent && conn->parent->state == BT_CONNECTED)
3854-
hci_le_create_cis(conn);
3852+
3853+
if (conn->state == BT_CONNECT)
3854+
pending = true;
38553855
}
38563856

38573857
unlock:
3858+
if (pending)
3859+
hci_le_create_cis_pending(hdev);
3860+
38583861
hci_dev_unlock(hdev);
38593862

38603863
return rp->status;
@@ -4220,6 +4223,7 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, void *data,
42204223
static void hci_cs_le_create_cis(struct hci_dev *hdev, u8 status)
42214224
{
42224225
struct hci_cp_le_create_cis *cp;
4226+
bool pending = false;
42234227
int i;
42244228

42254229
bt_dev_dbg(hdev, "status 0x%2.2x", status);
@@ -4242,12 +4246,18 @@ static void hci_cs_le_create_cis(struct hci_dev *hdev, u8 status)
42424246

42434247
conn = hci_conn_hash_lookup_handle(hdev, handle);
42444248
if (conn) {
4249+
if (test_and_clear_bit(HCI_CONN_CREATE_CIS,
4250+
&conn->flags))
4251+
pending = true;
42454252
conn->state = BT_CLOSED;
42464253
hci_connect_cfm(conn, status);
42474254
hci_conn_del(conn);
42484255
}
42494256
}
42504257

4258+
if (pending)
4259+
hci_le_create_cis_pending(hdev);
4260+
42514261
hci_dev_unlock(hdev);
42524262
}
42534263

@@ -6790,6 +6800,7 @@ static void hci_le_cis_estabilished_evt(struct hci_dev *hdev, void *data,
67906800
{
67916801
struct hci_evt_le_cis_established *ev = data;
67926802
struct hci_conn *conn;
6803+
bool pending = false;
67936804
u16 handle = __le16_to_cpu(ev->handle);
67946805

67956806
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
@@ -6811,6 +6822,8 @@ static void hci_le_cis_estabilished_evt(struct hci_dev *hdev, void *data,
68116822
goto unlock;
68126823
}
68136824

6825+
pending = test_and_clear_bit(HCI_CONN_CREATE_CIS, &conn->flags);
6826+
68146827
if (conn->role == HCI_ROLE_SLAVE) {
68156828
__le32 interval;
68166829

@@ -6836,10 +6849,14 @@ static void hci_le_cis_estabilished_evt(struct hci_dev *hdev, void *data,
68366849
goto unlock;
68376850
}
68386851

6852+
conn->state = BT_CLOSED;
68396853
hci_connect_cfm(conn, ev->status);
68406854
hci_conn_del(conn);
68416855

68426856
unlock:
6857+
if (pending)
6858+
hci_le_create_cis_pending(hdev);
6859+
68436860
hci_dev_unlock(hdev);
68446861
}
68456862

net/bluetooth/hci_sync.c

+63-27
Original file line numberDiff line numberDiff line change
@@ -6165,56 +6165,92 @@ int hci_le_create_conn_sync(struct hci_dev *hdev, struct hci_conn *conn)
61656165
return err;
61666166
}
61676167

6168-
int hci_le_create_cis_sync(struct hci_dev *hdev, struct hci_conn *conn)
6168+
int hci_le_create_cis_sync(struct hci_dev *hdev)
61696169
{
61706170
struct {
61716171
struct hci_cp_le_create_cis cp;
61726172
struct hci_cis cis[0x1f];
61736173
} cmd;
6174-
u8 cig;
6175-
struct hci_conn *hcon = conn;
6174+
struct hci_conn *conn;
6175+
u8 cig = BT_ISO_QOS_CIG_UNSET;
6176+
6177+
/* The spec allows only one pending LE Create CIS command at a time. If
6178+
* the command is pending now, don't do anything. We check for pending
6179+
* connections after each CIS Established event.
6180+
*
6181+
* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 4, Part E
6182+
* page 2566:
6183+
*
6184+
* If the Host issues this command before all the
6185+
* HCI_LE_CIS_Established events from the previous use of the
6186+
* command have been generated, the Controller shall return the
6187+
* error code Command Disallowed (0x0C).
6188+
*
6189+
* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 4, Part E
6190+
* page 2567:
6191+
*
6192+
* When the Controller receives the HCI_LE_Create_CIS command, the
6193+
* Controller sends the HCI_Command_Status event to the Host. An
6194+
* HCI_LE_CIS_Established event will be generated for each CIS when it
6195+
* is established or if it is disconnected or considered lost before
6196+
* being established; until all the events are generated, the command
6197+
* remains pending.
6198+
*/
61766199

61776200
memset(&cmd, 0, sizeof(cmd));
6178-
cmd.cis[0].acl_handle = cpu_to_le16(conn->parent->handle);
6179-
cmd.cis[0].cis_handle = cpu_to_le16(conn->handle);
6180-
cmd.cp.num_cis++;
6181-
cig = conn->iso_qos.ucast.cig;
61826201

61836202
hci_dev_lock(hdev);
61846203

61856204
rcu_read_lock();
61866205

6206+
/* Wait until previous Create CIS has completed */
61876207
list_for_each_entry_rcu(conn, &hdev->conn_hash.list, list) {
6188-
struct hci_cis *cis = &cmd.cis[cmd.cp.num_cis];
6208+
if (test_bit(HCI_CONN_CREATE_CIS, &conn->flags))
6209+
goto done;
6210+
}
61896211

6190-
if (conn == hcon || conn->type != ISO_LINK ||
6191-
conn->state == BT_CONNECTED ||
6192-
conn->iso_qos.ucast.cig != cig)
6212+
/* Find CIG with all CIS ready */
6213+
list_for_each_entry_rcu(conn, &hdev->conn_hash.list, list) {
6214+
struct hci_conn *link;
6215+
6216+
if (hci_conn_check_create_cis(conn))
61936217
continue;
61946218

6195-
/* Check if all CIS(s) belonging to a CIG are ready */
6196-
if (!conn->parent || conn->parent->state != BT_CONNECTED ||
6197-
conn->state != BT_CONNECT) {
6198-
cmd.cp.num_cis = 0;
6199-
break;
6219+
cig = conn->iso_qos.ucast.cig;
6220+
6221+
list_for_each_entry_rcu(link, &hdev->conn_hash.list, list) {
6222+
if (hci_conn_check_create_cis(link) > 0 &&
6223+
link->iso_qos.ucast.cig == cig &&
6224+
link->state != BT_CONNECTED) {
6225+
cig = BT_ISO_QOS_CIG_UNSET;
6226+
break;
6227+
}
62006228
}
62016229

6202-
/* Group all CIS with state BT_CONNECT since the spec don't
6203-
* allow to send them individually:
6204-
*
6205-
* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 4, Part E
6206-
* page 2566:
6207-
*
6208-
* If the Host issues this command before all the
6209-
* HCI_LE_CIS_Established events from the previous use of the
6210-
* command have been generated, the Controller shall return the
6211-
* error code Command Disallowed (0x0C).
6212-
*/
6230+
if (cig != BT_ISO_QOS_CIG_UNSET)
6231+
break;
6232+
}
6233+
6234+
if (cig == BT_ISO_QOS_CIG_UNSET)
6235+
goto done;
6236+
6237+
list_for_each_entry_rcu(conn, &hdev->conn_hash.list, list) {
6238+
struct hci_cis *cis = &cmd.cis[cmd.cp.num_cis];
6239+
6240+
if (hci_conn_check_create_cis(conn) ||
6241+
conn->iso_qos.ucast.cig != cig)
6242+
continue;
6243+
6244+
set_bit(HCI_CONN_CREATE_CIS, &conn->flags);
62136245
cis->acl_handle = cpu_to_le16(conn->parent->handle);
62146246
cis->cis_handle = cpu_to_le16(conn->handle);
62156247
cmd.cp.num_cis++;
6248+
6249+
if (cmd.cp.num_cis >= ARRAY_SIZE(cmd.cis))
6250+
break;
62166251
}
62176252

6253+
done:
62186254
rcu_read_unlock();
62196255

62206256
hci_dev_unlock(hdev);

net/bluetooth/iso.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1681,7 +1681,7 @@ static void iso_connect_cfm(struct hci_conn *hcon, __u8 status)
16811681
}
16821682

16831683
/* Create CIS if pending */
1684-
hci_le_create_cis(hcon);
1684+
hci_le_create_cis_pending(hcon->hdev);
16851685
return;
16861686
}
16871687

0 commit comments

Comments
 (0)