Skip to content

Commit 5ae3d65

Browse files
iulia-tanasescusmb49
authored andcommitted
Bluetooth: ISO: Do not emit LE BIG Create Sync if previous is pending
BugLink: https://bugs.launchpad.net/bugs/2101915 [ Upstream commit 42ecf1947135110ea08abeaca39741636f9a2285 ] The Bluetooth Core spec does not allow a LE BIG Create sync command to be sent to Controller if another one is pending (Vol 4, Part E, page 2586). In order to avoid this issue, the HCI_CONN_CREATE_BIG_SYNC was added to mark that the LE BIG Create Sync command has been sent for a hcon. Once the BIG Sync Established event is received, the hcon flag is erased and the next pending hcon is handled. Signed-off-by: Iulia Tanasescu <iulia.tanasescu@nxp.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Stable-dep-of: 07a9342b94a9 ("Bluetooth: ISO: Send BIG Create Sync via hci_sync") Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Koichiro Den <koichiro.den@canonical.com> Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
1 parent 202aac1 commit 5ae3d65

File tree

5 files changed

+125
-16
lines changed

5 files changed

+125
-16
lines changed

include/net/bluetooth/hci.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#define HCI_MAX_ACL_SIZE 1024
3030
#define HCI_MAX_SCO_SIZE 255
3131
#define HCI_MAX_ISO_SIZE 251
32+
#define HCI_MAX_ISO_BIS 31
3233
#define HCI_MAX_EVENT_SIZE 260
3334
#define HCI_MAX_FRAME_SIZE (HCI_MAX_ACL_SIZE + 4)
3435

include/net/bluetooth/hci_core.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,9 @@ struct hci_conn {
712712
__s8 tx_power;
713713
__s8 max_tx_power;
714714
struct bt_iso_qos iso_qos;
715+
__u8 num_bis;
716+
__u8 bis[HCI_MAX_ISO_BIS];
717+
715718
unsigned long flags;
716719

717720
enum conn_reasons conn_reason;
@@ -947,6 +950,7 @@ enum {
947950
HCI_CONN_PER_ADV,
948951
HCI_CONN_BIG_CREATED,
949952
HCI_CONN_CREATE_CIS,
953+
HCI_CONN_CREATE_BIG_SYNC,
950954
HCI_CONN_BIG_SYNC,
951955
HCI_CONN_BIG_SYNC_FAILED,
952956
HCI_CONN_CREATE_PA_SYNC,
@@ -1296,6 +1300,30 @@ static inline struct hci_conn *hci_conn_hash_lookup_big(struct hci_dev *hdev,
12961300
return NULL;
12971301
}
12981302

1303+
static inline struct hci_conn *
1304+
hci_conn_hash_lookup_big_sync_pend(struct hci_dev *hdev,
1305+
__u8 handle, __u8 num_bis)
1306+
{
1307+
struct hci_conn_hash *h = &hdev->conn_hash;
1308+
struct hci_conn *c;
1309+
1310+
rcu_read_lock();
1311+
1312+
list_for_each_entry_rcu(c, &h->list, list) {
1313+
if (c->type != ISO_LINK)
1314+
continue;
1315+
1316+
if (handle == c->iso_qos.bcast.big && num_bis == c->num_bis) {
1317+
rcu_read_unlock();
1318+
return c;
1319+
}
1320+
}
1321+
1322+
rcu_read_unlock();
1323+
1324+
return NULL;
1325+
}
1326+
12991327
static inline struct hci_conn *
13001328
hci_conn_hash_lookup_big_state(struct hci_dev *hdev, __u8 handle, __u16 state)
13011329
{
@@ -1480,6 +1508,7 @@ void hci_sco_setup(struct hci_conn *conn, __u8 status);
14801508
bool hci_iso_setup_path(struct hci_conn *conn);
14811509
int hci_le_create_cis_pending(struct hci_dev *hdev);
14821510
int hci_pa_create_sync_pending(struct hci_dev *hdev);
1511+
int hci_le_big_create_sync_pending(struct hci_dev *hdev);
14831512
int hci_conn_check_create_cis(struct hci_conn *conn);
14841513

14851514
struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,

net/bluetooth/hci_conn.c

Lines changed: 73 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2188,34 +2188,93 @@ struct hci_conn *hci_pa_create_sync(struct hci_dev *hdev, bdaddr_t *dst,
21882188
return conn;
21892189
}
21902190

2191+
static bool hci_conn_check_create_big_sync(struct hci_conn *conn)
2192+
{
2193+
if (!conn->num_bis)
2194+
return false;
2195+
2196+
return true;
2197+
}
2198+
2199+
int hci_le_big_create_sync_pending(struct hci_dev *hdev)
2200+
{
2201+
DEFINE_FLEX(struct hci_cp_le_big_create_sync, pdu, bis, num_bis, 0x11);
2202+
struct hci_conn *conn;
2203+
2204+
rcu_read_lock();
2205+
2206+
pdu->num_bis = 0;
2207+
2208+
/* The spec allows only one pending LE BIG Create Sync command at
2209+
* a time. If the command is pending now, don't do anything. We
2210+
* check for pending connections after each BIG Sync Established
2211+
* event.
2212+
*
2213+
* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 4, Part E
2214+
* page 2586:
2215+
*
2216+
* If the Host sends this command when the Controller is in the
2217+
* process of synchronizing to any BIG, i.e. the HCI_LE_BIG_Sync_
2218+
* Established event has not been generated, the Controller shall
2219+
* return the error code Command Disallowed (0x0C).
2220+
*/
2221+
list_for_each_entry_rcu(conn, &hdev->conn_hash.list, list) {
2222+
if (test_bit(HCI_CONN_CREATE_BIG_SYNC, &conn->flags))
2223+
goto unlock;
2224+
}
2225+
2226+
list_for_each_entry_rcu(conn, &hdev->conn_hash.list, list) {
2227+
if (hci_conn_check_create_big_sync(conn)) {
2228+
struct bt_iso_qos *qos = &conn->iso_qos;
2229+
2230+
set_bit(HCI_CONN_CREATE_BIG_SYNC, &conn->flags);
2231+
2232+
pdu->handle = qos->bcast.big;
2233+
pdu->sync_handle = cpu_to_le16(conn->sync_handle);
2234+
pdu->encryption = qos->bcast.encryption;
2235+
memcpy(pdu->bcode, qos->bcast.bcode,
2236+
sizeof(pdu->bcode));
2237+
pdu->mse = qos->bcast.mse;
2238+
pdu->timeout = cpu_to_le16(qos->bcast.timeout);
2239+
pdu->num_bis = conn->num_bis;
2240+
memcpy(pdu->bis, conn->bis, conn->num_bis);
2241+
2242+
break;
2243+
}
2244+
}
2245+
2246+
unlock:
2247+
rcu_read_unlock();
2248+
2249+
if (!pdu->num_bis)
2250+
return 0;
2251+
2252+
return hci_send_cmd(hdev, HCI_OP_LE_BIG_CREATE_SYNC,
2253+
struct_size(pdu, bis, pdu->num_bis), pdu);
2254+
}
2255+
21912256
int hci_le_big_create_sync(struct hci_dev *hdev, struct hci_conn *hcon,
21922257
struct bt_iso_qos *qos,
21932258
__u16 sync_handle, __u8 num_bis, __u8 bis[])
21942259
{
2195-
DEFINE_FLEX(struct hci_cp_le_big_create_sync, pdu, bis, num_bis, 0x11);
21962260
int err;
21972261

2198-
if (num_bis < 0x01 || num_bis > pdu->num_bis)
2262+
if (num_bis < 0x01 || num_bis > ISO_MAX_NUM_BIS)
21992263
return -EINVAL;
22002264

22012265
err = qos_set_big(hdev, qos);
22022266
if (err)
22032267
return err;
22042268

2205-
if (hcon)
2206-
hcon->iso_qos.bcast.big = qos->bcast.big;
2269+
if (hcon) {
2270+
/* Update hcon QoS */
2271+
hcon->iso_qos = *qos;
22072272

2208-
pdu->handle = qos->bcast.big;
2209-
pdu->sync_handle = cpu_to_le16(sync_handle);
2210-
pdu->encryption = qos->bcast.encryption;
2211-
memcpy(pdu->bcode, qos->bcast.bcode, sizeof(pdu->bcode));
2212-
pdu->mse = qos->bcast.mse;
2213-
pdu->timeout = cpu_to_le16(qos->bcast.timeout);
2214-
pdu->num_bis = num_bis;
2215-
memcpy(pdu->bis, bis, num_bis);
2273+
hcon->num_bis = num_bis;
2274+
memcpy(hcon->bis, bis, num_bis);
2275+
}
22162276

2217-
return hci_send_cmd(hdev, HCI_OP_LE_BIG_CREATE_SYNC,
2218-
struct_size(pdu, bis, num_bis), pdu);
2277+
return hci_le_big_create_sync_pending(hdev);
22192278
}
22202279

22212280
static void create_big_complete(struct hci_dev *hdev, void *data, int err)

net/bluetooth/hci_event.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6914,7 +6914,7 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data,
69146914
struct sk_buff *skb)
69156915
{
69166916
struct hci_evt_le_big_sync_estabilished *ev = data;
6917-
struct hci_conn *bis;
6917+
struct hci_conn *bis, *conn;
69186918
int i;
69196919

69206920
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
@@ -6925,6 +6925,20 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data,
69256925

69266926
hci_dev_lock(hdev);
69276927

6928+
conn = hci_conn_hash_lookup_big_sync_pend(hdev, ev->handle,
6929+
ev->num_bis);
6930+
if (!conn) {
6931+
bt_dev_err(hdev,
6932+
"Unable to find connection for big 0x%2.2x",
6933+
ev->handle);
6934+
goto unlock;
6935+
}
6936+
6937+
clear_bit(HCI_CONN_CREATE_BIG_SYNC, &conn->flags);
6938+
6939+
conn->num_bis = 0;
6940+
memset(conn->bis, 0, sizeof(conn->num_bis));
6941+
69286942
for (i = 0; i < ev->num_bis; i++) {
69296943
u16 handle = le16_to_cpu(ev->bis[i]);
69306944
__le32 interval;
@@ -6974,6 +6988,10 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data,
69746988
hci_connect_cfm(bis, ev->status);
69756989
}
69766990

6991+
unlock:
6992+
/* Handle any other pending BIG sync command */
6993+
hci_le_big_create_sync_pending(hdev);
6994+
69776995
hci_dev_unlock(hdev);
69786996
}
69796997

net/bluetooth/iso.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2001,6 +2001,7 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
20012001

20022002
if (sk) {
20032003
int err;
2004+
struct hci_conn *hcon = iso_pi(sk)->conn->hcon;
20042005

20052006
iso_pi(sk)->qos.bcast.encryption = ev2->encryption;
20062007

@@ -2009,7 +2010,8 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
20092010

20102011
if (!test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags) &&
20112012
!test_and_set_bit(BT_SK_BIG_SYNC, &iso_pi(sk)->flags)) {
2012-
err = hci_le_big_create_sync(hdev, NULL,
2013+
err = hci_le_big_create_sync(hdev,
2014+
hcon,
20132015
&iso_pi(sk)->qos,
20142016
iso_pi(sk)->sync_handle,
20152017
iso_pi(sk)->bc_num_bis,

0 commit comments

Comments
 (0)