Skip to content

Commit 0614974

Browse files
committed
Bluetooth: hci_conn: Add support for linking multiple hcon
Since it is required for some configurations to have multiple CIS with the same peer which is now covered by iso-tester in the following test cases: ISO AC 6(i) - Success ISO AC 7(i) - Success ISO AC 8(i) - Success ISO AC 9(i) - Success ISO AC 11(i) - Success Signed-off-by: Luiz Augusto von Dentz <[email protected]>
1 parent e4eea89 commit 0614974

File tree

4 files changed

+172
-97
lines changed

4 files changed

+172
-97
lines changed

include/net/bluetooth/hci_core.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -770,7 +770,10 @@ struct hci_conn {
770770
void *iso_data;
771771
struct amp_mgr *amp_mgr;
772772

773-
struct hci_conn *link;
773+
struct list_head link_list;
774+
struct hci_conn *parent;
775+
struct hci_link *link;
776+
774777
struct bt_codec codec;
775778

776779
void (*connect_cfm_cb) (struct hci_conn *conn, u8 status);
@@ -780,6 +783,11 @@ struct hci_conn {
780783
void (*cleanup)(struct hci_conn *conn);
781784
};
782785

786+
struct hci_link {
787+
struct list_head list;
788+
struct hci_conn *conn;
789+
};
790+
783791
struct hci_chan {
784792
struct list_head list;
785793
__u16 handle;
@@ -1383,12 +1391,14 @@ static inline void hci_conn_put(struct hci_conn *conn)
13831391
put_device(&conn->dev);
13841392
}
13851393

1386-
static inline void hci_conn_hold(struct hci_conn *conn)
1394+
static inline struct hci_conn *hci_conn_hold(struct hci_conn *conn)
13871395
{
13881396
BT_DBG("hcon %p orig refcnt %d", conn, atomic_read(&conn->refcnt));
13891397

13901398
atomic_inc(&conn->refcnt);
13911399
cancel_delayed_work(&conn->disc_work);
1400+
1401+
return conn;
13921402
}
13931403

13941404
static inline void hci_conn_drop(struct hci_conn *conn)

net/bluetooth/hci_conn.c

Lines changed: 113 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -330,8 +330,11 @@ static void hci_add_sco(struct hci_conn *conn, __u16 handle)
330330
static bool find_next_esco_param(struct hci_conn *conn,
331331
const struct sco_param *esco_param, int size)
332332
{
333+
if (!conn->parent)
334+
return false;
335+
333336
for (; conn->attempt <= size; conn->attempt++) {
334-
if (lmp_esco_2m_capable(conn->link) ||
337+
if (lmp_esco_2m_capable(conn->parent) ||
335338
(esco_param[conn->attempt - 1].pkt_type & ESCO_2EV3))
336339
break;
337340
BT_DBG("hcon %p skipped attempt %d, eSCO 2M not supported",
@@ -461,7 +464,7 @@ static int hci_enhanced_setup_sync(struct hci_dev *hdev, void *data)
461464
break;
462465

463466
case BT_CODEC_CVSD:
464-
if (lmp_esco_capable(conn->link)) {
467+
if (conn->parent && lmp_esco_capable(conn->parent)) {
465468
if (!find_next_esco_param(conn, esco_param_cvsd,
466469
ARRAY_SIZE(esco_param_cvsd)))
467470
return -EINVAL;
@@ -531,7 +534,7 @@ static bool hci_setup_sync_conn(struct hci_conn *conn, __u16 handle)
531534
param = &esco_param_msbc[conn->attempt - 1];
532535
break;
533536
case SCO_AIRMODE_CVSD:
534-
if (lmp_esco_capable(conn->link)) {
537+
if (conn->parent && lmp_esco_capable(conn->parent)) {
535538
if (!find_next_esco_param(conn, esco_param_cvsd,
536539
ARRAY_SIZE(esco_param_cvsd)))
537540
return false;
@@ -637,21 +640,22 @@ void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __le64 rand,
637640
/* Device _must_ be locked */
638641
void hci_sco_setup(struct hci_conn *conn, __u8 status)
639642
{
640-
struct hci_conn *sco = conn->link;
643+
struct hci_link *link;
641644

642-
if (!sco)
645+
link = list_first_entry_or_null(&conn->link_list, struct hci_link, list);
646+
if (!link || !link->conn)
643647
return;
644648

645649
BT_DBG("hcon %p", conn);
646650

647651
if (!status) {
648652
if (lmp_esco_capable(conn->hdev))
649-
hci_setup_sync(sco, conn->handle);
653+
hci_setup_sync(link->conn, conn->handle);
650654
else
651-
hci_add_sco(sco, conn->handle);
655+
hci_add_sco(link->conn, conn->handle);
652656
} else {
653-
hci_connect_cfm(sco, status);
654-
hci_conn_del(sco);
657+
hci_connect_cfm(link->conn, status);
658+
hci_conn_del(link->conn);
655659
}
656660
}
657661

@@ -1042,6 +1046,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
10421046
skb_queue_head_init(&conn->data_q);
10431047

10441048
INIT_LIST_HEAD(&conn->chan_list);
1049+
INIT_LIST_HEAD(&conn->link_list);
10451050

10461051
INIT_DELAYED_WORK(&conn->disc_work, hci_conn_timeout);
10471052
INIT_DELAYED_WORK(&conn->auto_accept_work, hci_conn_auto_accept);
@@ -1069,15 +1074,39 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
10691074
return conn;
10701075
}
10711076

1072-
static bool hci_conn_unlink(struct hci_conn *conn)
1077+
static void hci_conn_unlink(struct hci_conn *conn)
10731078
{
1079+
struct hci_dev *hdev = conn->hdev;
1080+
1081+
bt_dev_dbg(hdev, "hcon %p", conn);
1082+
1083+
if (!conn->parent) {
1084+
struct hci_link *link, *t;
1085+
1086+
list_for_each_entry_safe(link, t, &conn->link_list, list)
1087+
hci_conn_unlink(link->conn);
1088+
1089+
return;
1090+
}
1091+
10741092
if (!conn->link)
1075-
return false;
1093+
return;
1094+
1095+
hci_conn_put(conn->parent);
1096+
conn->parent = NULL;
10761097

1077-
conn->link->link = NULL;
1098+
list_del_rcu(&conn->link->list);
1099+
synchronize_rcu();
1100+
1101+
kfree(conn->link);
10781102
conn->link = NULL;
10791103

1080-
return true;
1104+
/* Due to race, SCO connection might be not established
1105+
* yet at this point. Delete it now, otherwise it is
1106+
* possible for it to be stuck and can't be deleted.
1107+
*/
1108+
if (conn->handle == HCI_CONN_HANDLE_UNSET)
1109+
hci_conn_del(conn);
10811110
}
10821111

10831112
int hci_conn_del(struct hci_conn *conn)
@@ -1091,18 +1120,7 @@ int hci_conn_del(struct hci_conn *conn)
10911120
cancel_delayed_work_sync(&conn->idle_work);
10921121

10931122
if (conn->type == ACL_LINK) {
1094-
struct hci_conn *link = conn->link;
1095-
1096-
if (link) {
1097-
hci_conn_unlink(conn);
1098-
/* Due to race, SCO connection might be not established
1099-
* yet at this point. Delete it now, otherwise it is
1100-
* possible for it to be stuck and can't be deleted.
1101-
*/
1102-
if (link->handle == HCI_CONN_HANDLE_UNSET)
1103-
hci_conn_del(link);
1104-
}
1105-
1123+
hci_conn_unlink(conn);
11061124
/* Unacked frames */
11071125
hdev->acl_cnt += conn->sent;
11081126
} else if (conn->type == LE_LINK) {
@@ -1113,7 +1131,7 @@ int hci_conn_del(struct hci_conn *conn)
11131131
else
11141132
hdev->acl_cnt += conn->sent;
11151133
} else {
1116-
struct hci_conn *acl = conn->link;
1134+
struct hci_conn *acl = conn->parent;
11171135

11181136
if (acl) {
11191137
hci_conn_unlink(conn);
@@ -1600,11 +1618,40 @@ struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
16001618
return acl;
16011619
}
16021620

1621+
static struct hci_link *hci_conn_link(struct hci_conn *parent,
1622+
struct hci_conn *conn)
1623+
{
1624+
struct hci_dev *hdev = parent->hdev;
1625+
struct hci_link *link;
1626+
1627+
bt_dev_dbg(hdev, "parent %p hcon %p", parent, conn);
1628+
1629+
if (conn->link)
1630+
return conn->link;
1631+
1632+
if (conn->parent)
1633+
return NULL;
1634+
1635+
link = kzalloc(sizeof(*link), GFP_KERNEL);
1636+
if (!link)
1637+
return NULL;
1638+
1639+
link->conn = hci_conn_hold(conn);
1640+
conn->link = link;
1641+
conn->parent = hci_conn_get(parent);
1642+
1643+
/* Use list_add_tail_rcu append to the list */
1644+
list_add_tail_rcu(&link->list, &parent->link_list);
1645+
1646+
return link;
1647+
}
1648+
16031649
struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst,
16041650
__u16 setting, struct bt_codec *codec)
16051651
{
16061652
struct hci_conn *acl;
16071653
struct hci_conn *sco;
1654+
struct hci_link *link;
16081655

16091656
acl = hci_connect_acl(hdev, dst, BT_SECURITY_LOW, HCI_AT_NO_BONDING,
16101657
CONN_REASON_SCO_CONNECT);
@@ -1620,10 +1667,12 @@ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst,
16201667
}
16211668
}
16221669

1623-
acl->link = sco;
1624-
sco->link = acl;
1625-
1626-
hci_conn_hold(sco);
1670+
link = hci_conn_link(acl, sco);
1671+
if (!link) {
1672+
hci_conn_drop(acl);
1673+
hci_conn_drop(sco);
1674+
return NULL;
1675+
}
16271676

16281677
sco->setting = setting;
16291678
sco->codec = *codec;
@@ -1890,7 +1939,7 @@ static int hci_create_cis_sync(struct hci_dev *hdev, void *data)
18901939
u8 cig;
18911940

18921941
memset(&cmd, 0, sizeof(cmd));
1893-
cmd.cis[0].acl_handle = cpu_to_le16(conn->link->handle);
1942+
cmd.cis[0].acl_handle = cpu_to_le16(conn->parent->handle);
18941943
cmd.cis[0].cis_handle = cpu_to_le16(conn->handle);
18951944
cmd.cp.num_cis++;
18961945
cig = conn->iso_qos.ucast.cig;
@@ -1903,11 +1952,12 @@ static int hci_create_cis_sync(struct hci_dev *hdev, void *data)
19031952
struct hci_cis *cis = &cmd.cis[cmd.cp.num_cis];
19041953

19051954
if (conn == data || conn->type != ISO_LINK ||
1906-
conn->state == BT_CONNECTED || conn->iso_qos.ucast.cig != cig)
1955+
conn->state == BT_CONNECTED ||
1956+
conn->iso_qos.ucast.cig != cig)
19071957
continue;
19081958

19091959
/* Check if all CIS(s) belonging to a CIG are ready */
1910-
if (!conn->link || conn->link->state != BT_CONNECTED ||
1960+
if (!conn->parent || conn->parent->state != BT_CONNECTED ||
19111961
conn->state != BT_CONNECT) {
19121962
cmd.cp.num_cis = 0;
19131963
break;
@@ -1924,7 +1974,7 @@ static int hci_create_cis_sync(struct hci_dev *hdev, void *data)
19241974
* command have been generated, the Controller shall return the
19251975
* error code Command Disallowed (0x0C).
19261976
*/
1927-
cis->acl_handle = cpu_to_le16(conn->link->handle);
1977+
cis->acl_handle = cpu_to_le16(conn->parent->handle);
19281978
cis->cis_handle = cpu_to_le16(conn->handle);
19291979
cmd.cp.num_cis++;
19301980
}
@@ -1943,15 +1993,33 @@ static int hci_create_cis_sync(struct hci_dev *hdev, void *data)
19431993
int hci_le_create_cis(struct hci_conn *conn)
19441994
{
19451995
struct hci_conn *cis;
1996+
struct hci_link *link, *t;
19461997
struct hci_dev *hdev = conn->hdev;
19471998
int err;
19481999

2000+
bt_dev_dbg(hdev, "hcon %p", conn);
2001+
19492002
switch (conn->type) {
19502003
case LE_LINK:
1951-
if (!conn->link || conn->state != BT_CONNECTED)
2004+
if (conn->state != BT_CONNECTED || list_empty(&conn->link_list))
19522005
return -EINVAL;
1953-
cis = conn->link;
1954-
break;
2006+
2007+
cis = NULL;
2008+
2009+
/* hci_conn_link uses list_add_tail_rcu so the list is in
2010+
* the same order as the connections are requested.
2011+
*/
2012+
list_for_each_entry_safe(link, t, &conn->link_list, list) {
2013+
if (link->conn->state == BT_BOUND) {
2014+
err = hci_le_create_cis(link->conn);
2015+
if (err)
2016+
return err;
2017+
2018+
cis = link->conn;
2019+
}
2020+
}
2021+
2022+
return cis ? 0 : -EINVAL;
19552023
case ISO_LINK:
19562024
cis = conn;
19572025
break;
@@ -2172,6 +2240,7 @@ struct hci_conn *hci_connect_cis(struct hci_dev *hdev, bdaddr_t *dst,
21722240
{
21732241
struct hci_conn *le;
21742242
struct hci_conn *cis;
2243+
struct hci_link *link;
21752244

21762245
if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
21772246
le = hci_connect_le(hdev, dst, dst_type, false,
@@ -2197,16 +2266,18 @@ struct hci_conn *hci_connect_cis(struct hci_dev *hdev, bdaddr_t *dst,
21972266
return cis;
21982267
}
21992268

2200-
le->link = cis;
2201-
cis->link = le;
2202-
2203-
hci_conn_hold(cis);
2269+
link = hci_conn_link(le, cis);
2270+
if (!link) {
2271+
hci_conn_drop(le);
2272+
hci_conn_drop(cis);
2273+
return NULL;
2274+
}
22042275

22052276
/* If LE is already connected and CIS handle is already set proceed to
22062277
* Create CIS immediately.
22072278
*/
22082279
if (le->state == BT_CONNECTED && cis->handle != HCI_CONN_HANDLE_UNSET)
2209-
hci_le_create_cis(le);
2280+
hci_le_create_cis(cis);
22102281

22112282
return cis;
22122283
}

0 commit comments

Comments
 (0)