Skip to content

Commit 7787833

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 <[email protected]> Signed-off-by: Luiz Augusto von Dentz <[email protected]>
1 parent 6064a38 commit 7787833

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
@@ -1990,59 +1990,47 @@ bool hci_iso_setup_path(struct hci_conn *conn)
19901990
return true;
19911991
}
19921992

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

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

2005-
bt_dev_dbg(hdev, "hcon %p", conn);
2002+
return 0;
2003+
}
20062004

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

2012-
cis = NULL;
2010+
int hci_le_create_cis_pending(struct hci_dev *hdev)
2011+
{
2012+
struct hci_conn *conn;
2013+
bool pending = false;
20132014

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

2023-
cis = link->conn;
2024-
}
2017+
list_for_each_entry_rcu(conn, &hdev->conn_hash.list, list) {
2018+
if (test_bit(HCI_CONN_CREATE_CIS, &conn->flags)) {
2019+
rcu_read_unlock();
2020+
return -EBUSY;
20252021
}
20262022

2027-
return cis ? 0 : -EINVAL;
2028-
case ISO_LINK:
2029-
cis = conn;
2030-
break;
2031-
default:
2032-
return -EINVAL;
2023+
if (!hci_conn_check_create_cis(conn))
2024+
pending = true;
20332025
}
20342026

2035-
if (cis->state == BT_CONNECT)
2027+
rcu_read_unlock();
2028+
2029+
if (!pending)
20362030
return 0;
20372031

20382032
/* Queue Create CIS */
2039-
err = hci_cmd_sync_queue(hdev, hci_create_cis_sync, cis, NULL);
2040-
if (err)
2041-
return err;
2042-
2043-
cis->state = BT_CONNECT;
2044-
2045-
return 0;
2033+
return hci_cmd_sync_queue(hdev, hci_create_cis_sync, NULL, NULL);
20462034
}
20472035

20482036
static void hci_iso_qos_setup(struct hci_dev *hdev, struct hci_conn *conn,
@@ -2317,11 +2305,9 @@ struct hci_conn *hci_connect_cis(struct hci_dev *hdev, bdaddr_t *dst,
23172305
return NULL;
23182306
}
23192307

2320-
/* If LE is already connected and CIS handle is already set proceed to
2321-
* Create CIS immediately.
2322-
*/
2323-
if (le->state == BT_CONNECTED && cis->handle != HCI_CONN_HANDLE_UNSET)
2324-
hci_le_create_cis(cis);
2308+
cis->state = BT_CONNECT;
2309+
2310+
hci_le_create_cis_pending(hdev);
23252311

23262312
return cis;
23272313
}

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);
@@ -3849,13 +3850,15 @@ static u8 hci_cc_le_set_cig_params(struct hci_dev *hdev, void *data,
38493850

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

38583858
unlock:
3859+
if (pending)
3860+
hci_le_create_cis_pending(hdev);
3861+
38593862
hci_dev_unlock(hdev);
38603863

38613864
return rp->status;
@@ -4221,6 +4224,7 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, void *data,
42214224
static void hci_cs_le_create_cis(struct hci_dev *hdev, u8 status)
42224225
{
42234226
struct hci_cp_le_create_cis *cp;
4227+
bool pending = false;
42244228
int i;
42254229

42264230
bt_dev_dbg(hdev, "status 0x%2.2x", status);
@@ -4243,12 +4247,18 @@ static void hci_cs_le_create_cis(struct hci_dev *hdev, u8 status)
42434247

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

4259+
if (pending)
4260+
hci_le_create_cis_pending(hdev);
4261+
42524262
hci_dev_unlock(hdev);
42534263
}
42544264

@@ -6787,6 +6797,7 @@ static void hci_le_cis_estabilished_evt(struct hci_dev *hdev, void *data,
67876797
struct hci_evt_le_cis_established *ev = data;
67886798
struct hci_conn *conn;
67896799
struct bt_iso_qos *qos;
6800+
bool pending = false;
67906801
u16 handle = __le16_to_cpu(ev->handle);
67916802

67926803
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
@@ -6810,6 +6821,8 @@ static void hci_le_cis_estabilished_evt(struct hci_dev *hdev, void *data,
68106821

68116822
qos = &conn->iso_qos;
68126823

6824+
pending = test_and_clear_bit(HCI_CONN_CREATE_CIS, &conn->flags);
6825+
68136826
/* Convert ISO Interval (1.25 ms slots) to SDU Interval (us) */
68146827
qos->ucast.in.interval = le16_to_cpu(ev->interval) * 1250;
68156828
qos->ucast.out.interval = qos->ucast.in.interval;
@@ -6851,10 +6864,14 @@ static void hci_le_cis_estabilished_evt(struct hci_dev *hdev, void *data,
68516864
goto unlock;
68526865
}
68536866

6867+
conn->state = BT_CLOSED;
68546868
hci_connect_cfm(conn, ev->status);
68556869
hci_conn_del(conn);
68566870

68576871
unlock:
6872+
if (pending)
6873+
hci_le_create_cis_pending(hdev);
6874+
68586875
hci_dev_unlock(hdev);
68596876
}
68606877

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)