Skip to content

Commit 1559c9c

Browse files
committed
Merge tag 'for-net-2025-08-22' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth
Luiz Augusto von Dentz says: ==================== bluetooth pull request for net: * tag 'for-net-2025-08-22' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth: Bluetooth: hci_sync: fix set_local_name race condition Bluetooth: hci_event: Disconnect device when BIG sync is lost Bluetooth: hci_event: Detect if HCI_EV_NUM_COMP_PKTS is unbalanced Bluetooth: hci_event: Mark connection as closed during suspend disconnect Bluetooth: hci_event: Treat UNKNOWN_CONN_ID on disconnect as success Bluetooth: hci_conn: Make unacked packet handling more robust ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents c61ac2e + 6bbd0d3 commit 1559c9c

File tree

5 files changed

+75
-25
lines changed

5 files changed

+75
-25
lines changed

include/net/bluetooth/hci_sync.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ int hci_update_class_sync(struct hci_dev *hdev);
9393

9494
int hci_update_eir_sync(struct hci_dev *hdev);
9595
int hci_update_class_sync(struct hci_dev *hdev);
96-
int hci_update_name_sync(struct hci_dev *hdev);
96+
int hci_update_name_sync(struct hci_dev *hdev, const u8 *name);
9797
int hci_write_ssp_mode_sync(struct hci_dev *hdev, u8 mode);
9898

9999
int hci_get_random_address(struct hci_dev *hdev, bool require_privacy,

net/bluetooth/hci_conn.c

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,6 @@ static void hci_conn_cleanup(struct hci_conn *conn)
149149

150150
hci_chan_list_flush(conn);
151151

152-
hci_conn_hash_del(hdev, conn);
153-
154152
if (HCI_CONN_HANDLE_UNSET(conn->handle))
155153
ida_free(&hdev->unset_handle_ida, conn->handle);
156154

@@ -1152,28 +1150,54 @@ void hci_conn_del(struct hci_conn *conn)
11521150
disable_delayed_work_sync(&conn->auto_accept_work);
11531151
disable_delayed_work_sync(&conn->idle_work);
11541152

1155-
if (conn->type == ACL_LINK) {
1156-
/* Unacked frames */
1157-
hdev->acl_cnt += conn->sent;
1158-
} else if (conn->type == LE_LINK) {
1159-
cancel_delayed_work(&conn->le_conn_timeout);
1153+
/* Remove the connection from the list so unacked logic can detect when
1154+
* a certain pool is not being utilized.
1155+
*/
1156+
hci_conn_hash_del(hdev, conn);
11601157

1161-
if (hdev->le_pkts)
1162-
hdev->le_cnt += conn->sent;
1158+
/* Handle unacked frames:
1159+
*
1160+
* - In case there are no connection, or if restoring the buffers
1161+
* considered in transist would overflow, restore all buffers to the
1162+
* pool.
1163+
* - Otherwise restore just the buffers considered in transit for the
1164+
* hci_conn
1165+
*/
1166+
switch (conn->type) {
1167+
case ACL_LINK:
1168+
if (!hci_conn_num(hdev, ACL_LINK) ||
1169+
hdev->acl_cnt + conn->sent > hdev->acl_pkts)
1170+
hdev->acl_cnt = hdev->acl_pkts;
11631171
else
11641172
hdev->acl_cnt += conn->sent;
1165-
} else {
1166-
/* Unacked ISO frames */
1167-
if (conn->type == CIS_LINK ||
1168-
conn->type == BIS_LINK ||
1169-
conn->type == PA_LINK) {
1170-
if (hdev->iso_pkts)
1171-
hdev->iso_cnt += conn->sent;
1172-
else if (hdev->le_pkts)
1173+
break;
1174+
case LE_LINK:
1175+
cancel_delayed_work(&conn->le_conn_timeout);
1176+
1177+
if (hdev->le_pkts) {
1178+
if (!hci_conn_num(hdev, LE_LINK) ||
1179+
hdev->le_cnt + conn->sent > hdev->le_pkts)
1180+
hdev->le_cnt = hdev->le_pkts;
1181+
else
11731182
hdev->le_cnt += conn->sent;
1183+
} else {
1184+
if ((!hci_conn_num(hdev, LE_LINK) &&
1185+
!hci_conn_num(hdev, ACL_LINK)) ||
1186+
hdev->acl_cnt + conn->sent > hdev->acl_pkts)
1187+
hdev->acl_cnt = hdev->acl_pkts;
11741188
else
11751189
hdev->acl_cnt += conn->sent;
11761190
}
1191+
break;
1192+
case CIS_LINK:
1193+
case BIS_LINK:
1194+
case PA_LINK:
1195+
if (!hci_iso_count(hdev) ||
1196+
hdev->iso_cnt + conn->sent > hdev->iso_pkts)
1197+
hdev->iso_cnt = hdev->iso_pkts;
1198+
else
1199+
hdev->iso_cnt += conn->sent;
1200+
break;
11771201
}
11781202

11791203
skb_queue_purge(&conn->data_q);

net/bluetooth/hci_event.c

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2703,7 +2703,7 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
27032703
if (!conn)
27042704
goto unlock;
27052705

2706-
if (status) {
2706+
if (status && status != HCI_ERROR_UNKNOWN_CONN_ID) {
27072707
mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
27082708
conn->dst_type, status);
27092709

@@ -2718,6 +2718,12 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
27182718
goto done;
27192719
}
27202720

2721+
/* During suspend, mark connection as closed immediately
2722+
* since we might not receive HCI_EV_DISCONN_COMPLETE
2723+
*/
2724+
if (hdev->suspended)
2725+
conn->state = BT_CLOSED;
2726+
27212727
mgmt_conn = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags);
27222728

27232729
if (conn->type == ACL_LINK) {
@@ -4398,7 +4404,17 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data,
43984404
if (!conn)
43994405
continue;
44004406

4401-
conn->sent -= count;
4407+
/* Check if there is really enough packets outstanding before
4408+
* attempting to decrease the sent counter otherwise it could
4409+
* underflow..
4410+
*/
4411+
if (conn->sent >= count) {
4412+
conn->sent -= count;
4413+
} else {
4414+
bt_dev_warn(hdev, "hcon %p sent %u < count %u",
4415+
conn, conn->sent, count);
4416+
conn->sent = 0;
4417+
}
44024418

44034419
for (i = 0; i < count; ++i)
44044420
hci_conn_tx_dequeue(conn);
@@ -7008,6 +7024,7 @@ static void hci_le_big_sync_lost_evt(struct hci_dev *hdev, void *data,
70087024
{
70097025
struct hci_evt_le_big_sync_lost *ev = data;
70107026
struct hci_conn *bis, *conn;
7027+
bool mgmt_conn;
70117028

70127029
bt_dev_dbg(hdev, "big handle 0x%2.2x", ev->handle);
70137030

@@ -7026,6 +7043,10 @@ static void hci_le_big_sync_lost_evt(struct hci_dev *hdev, void *data,
70267043
while ((bis = hci_conn_hash_lookup_big_state(hdev, ev->handle,
70277044
BT_CONNECTED,
70287045
HCI_ROLE_SLAVE))) {
7046+
mgmt_conn = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &bis->flags);
7047+
mgmt_device_disconnected(hdev, &bis->dst, bis->type, bis->dst_type,
7048+
ev->reason, mgmt_conn);
7049+
70297050
clear_bit(HCI_CONN_BIG_SYNC, &bis->flags);
70307051
hci_disconn_cfm(bis, ev->reason);
70317052
hci_conn_del(bis);

net/bluetooth/hci_sync.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3481,13 +3481,13 @@ int hci_update_scan_sync(struct hci_dev *hdev)
34813481
return hci_write_scan_enable_sync(hdev, scan);
34823482
}
34833483

3484-
int hci_update_name_sync(struct hci_dev *hdev)
3484+
int hci_update_name_sync(struct hci_dev *hdev, const u8 *name)
34853485
{
34863486
struct hci_cp_write_local_name cp;
34873487

34883488
memset(&cp, 0, sizeof(cp));
34893489

3490-
memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
3490+
memcpy(cp.name, name, sizeof(cp.name));
34913491

34923492
return __hci_cmd_sync_status(hdev, HCI_OP_WRITE_LOCAL_NAME,
34933493
sizeof(cp), &cp,
@@ -3540,7 +3540,7 @@ int hci_powered_update_sync(struct hci_dev *hdev)
35403540
hci_write_fast_connectable_sync(hdev, false);
35413541
hci_update_scan_sync(hdev);
35423542
hci_update_class_sync(hdev);
3543-
hci_update_name_sync(hdev);
3543+
hci_update_name_sync(hdev, hdev->dev_name);
35443544
hci_update_eir_sync(hdev);
35453545
}
35463546

net/bluetooth/mgmt.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3892,8 +3892,11 @@ static void set_name_complete(struct hci_dev *hdev, void *data, int err)
38923892

38933893
static int set_name_sync(struct hci_dev *hdev, void *data)
38943894
{
3895+
struct mgmt_pending_cmd *cmd = data;
3896+
struct mgmt_cp_set_local_name *cp = cmd->param;
3897+
38953898
if (lmp_bredr_capable(hdev)) {
3896-
hci_update_name_sync(hdev);
3899+
hci_update_name_sync(hdev, cp->name);
38973900
hci_update_eir_sync(hdev);
38983901
}
38993902

@@ -9705,7 +9708,9 @@ void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
97059708
if (!mgmt_connected)
97069709
return;
97079710

9708-
if (link_type != ACL_LINK && link_type != LE_LINK)
9711+
if (link_type != ACL_LINK &&
9712+
link_type != LE_LINK &&
9713+
link_type != BIS_LINK)
97099714
return;
97109715

97119716
bacpy(&ev.addr.bdaddr, bdaddr);

0 commit comments

Comments
 (0)