Skip to content

Commit 21319d2

Browse files
pvAndrea Righi
authored and
Andrea Righi
committed
Bluetooth: ISO: do not emit new LE Create CIS if previous is pending
BugLink: https://bugs.launchpad.net/bugs/2035588 [ Upstream commit 7f74563 ] 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]> Signed-off-by: Sasha Levin <[email protected]> Signed-off-by: Andrea Righi <[email protected]>
1 parent 1f75eb4 commit 21319d2

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
@@ -975,6 +975,7 @@ enum {
975975
HCI_CONN_AUTH_FAILURE,
976976
HCI_CONN_PER_ADV,
977977
HCI_CONN_BIG_CREATED,
978+
HCI_CONN_CREATE_CIS,
978979
};
979980

980981
static inline bool hci_conn_ssp_enabled(struct hci_conn *conn)
@@ -1351,7 +1352,8 @@ int hci_disconnect(struct hci_conn *conn, __u8 reason);
13511352
bool hci_setup_sync(struct hci_conn *conn, __u16 handle);
13521353
void hci_sco_setup(struct hci_conn *conn, __u8 status);
13531354
bool hci_iso_setup_path(struct hci_conn *conn);
1354-
int hci_le_create_cis(struct hci_conn *conn);
1355+
int hci_le_create_cis_pending(struct hci_dev *hdev);
1356+
int hci_conn_check_create_cis(struct hci_conn *conn);
13551357

13561358
struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
13571359
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 ERR_PTR(-ENOLINK);
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
@@ -3810,6 +3810,7 @@ static u8 hci_cc_le_set_cig_params(struct hci_dev *hdev, void *data,
38103810
struct hci_cp_le_set_cig_params *cp;
38113811
struct hci_conn *conn;
38123812
u8 status = rp->status;
3813+
bool pending = false;
38133814
int i;
38143815

38153816
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
@@ -3852,13 +3853,15 @@ static u8 hci_cc_le_set_cig_params(struct hci_dev *hdev, void *data,
38523853

38533854
bt_dev_dbg(hdev, "%p handle 0x%4.4x parent %p", conn,
38543855
conn->handle, conn->parent);
3855-
3856-
/* Create CIS if LE is already connected */
3857-
if (conn->parent && conn->parent->state == BT_CONNECTED)
3858-
hci_le_create_cis(conn);
3856+
3857+
if (conn->state == BT_CONNECT)
3858+
pending = true;
38593859
}
38603860

38613861
unlock:
3862+
if (pending)
3863+
hci_le_create_cis_pending(hdev);
3864+
38623865
hci_dev_unlock(hdev);
38633866

38643867
return rp->status;
@@ -4224,6 +4227,7 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, void *data,
42244227
static void hci_cs_le_create_cis(struct hci_dev *hdev, u8 status)
42254228
{
42264229
struct hci_cp_le_create_cis *cp;
4230+
bool pending = false;
42274231
int i;
42284232

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

42474251
conn = hci_conn_hash_lookup_handle(hdev, handle);
42484252
if (conn) {
4253+
if (test_and_clear_bit(HCI_CONN_CREATE_CIS,
4254+
&conn->flags))
4255+
pending = true;
42494256
conn->state = BT_CLOSED;
42504257
hci_connect_cfm(conn, status);
42514258
hci_conn_del(conn);
42524259
}
42534260
}
42544261

4262+
if (pending)
4263+
hci_le_create_cis_pending(hdev);
4264+
42554265
hci_dev_unlock(hdev);
42564266
}
42574267

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

67956806
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
@@ -6813,6 +6824,8 @@ static void hci_le_cis_estabilished_evt(struct hci_dev *hdev, void *data,
68136824

68146825
qos = &conn->iso_qos;
68156826

6827+
pending = test_and_clear_bit(HCI_CONN_CREATE_CIS, &conn->flags);
6828+
68166829
/* Convert ISO Interval (1.25 ms slots) to SDU Interval (us) */
68176830
qos->ucast.in.interval = le16_to_cpu(ev->interval) * 1250;
68186831
qos->ucast.out.interval = qos->ucast.in.interval;
@@ -6854,10 +6867,14 @@ static void hci_le_cis_estabilished_evt(struct hci_dev *hdev, void *data,
68546867
goto unlock;
68556868
}
68566869

6870+
conn->state = BT_CLOSED;
68576871
hci_connect_cfm(conn, ev->status);
68586872
hci_conn_del(conn);
68596873

68606874
unlock:
6875+
if (pending)
6876+
hci_le_create_cis_pending(hdev);
6877+
68616878
hci_dev_unlock(hdev);
68626879
}
68636880

net/bluetooth/hci_sync.c

+63-27
Original file line numberDiff line numberDiff line change
@@ -6260,56 +6260,92 @@ int hci_le_create_conn_sync(struct hci_dev *hdev, struct hci_conn *conn)
62606260
return err;
62616261
}
62626262

6263-
int hci_le_create_cis_sync(struct hci_dev *hdev, struct hci_conn *conn)
6263+
int hci_le_create_cis_sync(struct hci_dev *hdev)
62646264
{
62656265
struct {
62666266
struct hci_cp_le_create_cis cp;
62676267
struct hci_cis cis[0x1f];
62686268
} cmd;
6269-
u8 cig;
6270-
struct hci_conn *hcon = conn;
6269+
struct hci_conn *conn;
6270+
u8 cig = BT_ISO_QOS_CIG_UNSET;
6271+
6272+
/* The spec allows only one pending LE Create CIS command at a time. If
6273+
* the command is pending now, don't do anything. We check for pending
6274+
* connections after each CIS Established event.
6275+
*
6276+
* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 4, Part E
6277+
* page 2566:
6278+
*
6279+
* If the Host issues this command before all the
6280+
* HCI_LE_CIS_Established events from the previous use of the
6281+
* command have been generated, the Controller shall return the
6282+
* error code Command Disallowed (0x0C).
6283+
*
6284+
* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 4, Part E
6285+
* page 2567:
6286+
*
6287+
* When the Controller receives the HCI_LE_Create_CIS command, the
6288+
* Controller sends the HCI_Command_Status event to the Host. An
6289+
* HCI_LE_CIS_Established event will be generated for each CIS when it
6290+
* is established or if it is disconnected or considered lost before
6291+
* being established; until all the events are generated, the command
6292+
* remains pending.
6293+
*/
62716294

62726295
memset(&cmd, 0, sizeof(cmd));
6273-
cmd.cis[0].acl_handle = cpu_to_le16(conn->parent->handle);
6274-
cmd.cis[0].cis_handle = cpu_to_le16(conn->handle);
6275-
cmd.cp.num_cis++;
6276-
cig = conn->iso_qos.ucast.cig;
62776296

62786297
hci_dev_lock(hdev);
62796298

62806299
rcu_read_lock();
62816300

6301+
/* Wait until previous Create CIS has completed */
62826302
list_for_each_entry_rcu(conn, &hdev->conn_hash.list, list) {
6283-
struct hci_cis *cis = &cmd.cis[cmd.cp.num_cis];
6303+
if (test_bit(HCI_CONN_CREATE_CIS, &conn->flags))
6304+
goto done;
6305+
}
62846306

6285-
if (conn == hcon || conn->type != ISO_LINK ||
6286-
conn->state == BT_CONNECTED ||
6287-
conn->iso_qos.ucast.cig != cig)
6307+
/* Find CIG with all CIS ready */
6308+
list_for_each_entry_rcu(conn, &hdev->conn_hash.list, list) {
6309+
struct hci_conn *link;
6310+
6311+
if (hci_conn_check_create_cis(conn))
62886312
continue;
62896313

6290-
/* Check if all CIS(s) belonging to a CIG are ready */
6291-
if (!conn->parent || conn->parent->state != BT_CONNECTED ||
6292-
conn->state != BT_CONNECT) {
6293-
cmd.cp.num_cis = 0;
6294-
break;
6314+
cig = conn->iso_qos.ucast.cig;
6315+
6316+
list_for_each_entry_rcu(link, &hdev->conn_hash.list, list) {
6317+
if (hci_conn_check_create_cis(link) > 0 &&
6318+
link->iso_qos.ucast.cig == cig &&
6319+
link->state != BT_CONNECTED) {
6320+
cig = BT_ISO_QOS_CIG_UNSET;
6321+
break;
6322+
}
62956323
}
62966324

6297-
/* Group all CIS with state BT_CONNECT since the spec don't
6298-
* allow to send them individually:
6299-
*
6300-
* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 4, Part E
6301-
* page 2566:
6302-
*
6303-
* If the Host issues this command before all the
6304-
* HCI_LE_CIS_Established events from the previous use of the
6305-
* command have been generated, the Controller shall return the
6306-
* error code Command Disallowed (0x0C).
6307-
*/
6325+
if (cig != BT_ISO_QOS_CIG_UNSET)
6326+
break;
6327+
}
6328+
6329+
if (cig == BT_ISO_QOS_CIG_UNSET)
6330+
goto done;
6331+
6332+
list_for_each_entry_rcu(conn, &hdev->conn_hash.list, list) {
6333+
struct hci_cis *cis = &cmd.cis[cmd.cp.num_cis];
6334+
6335+
if (hci_conn_check_create_cis(conn) ||
6336+
conn->iso_qos.ucast.cig != cig)
6337+
continue;
6338+
6339+
set_bit(HCI_CONN_CREATE_CIS, &conn->flags);
63086340
cis->acl_handle = cpu_to_le16(conn->parent->handle);
63096341
cis->cis_handle = cpu_to_le16(conn->handle);
63106342
cmd.cp.num_cis++;
6343+
6344+
if (cmd.cp.num_cis >= ARRAY_SIZE(cmd.cis))
6345+
break;
63116346
}
63126347

6348+
done:
63136349
rcu_read_unlock();
63146350

63156351
hci_dev_unlock(hdev);

net/bluetooth/iso.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1690,7 +1690,7 @@ static void iso_connect_cfm(struct hci_conn *hcon, __u8 status)
16901690
}
16911691

16921692
/* Create CIS if pending */
1693-
hci_le_create_cis(hcon);
1693+
hci_le_create_cis_pending(hcon->hdev);
16941694
return;
16951695
}
16961696

0 commit comments

Comments
 (0)