Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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/20250822180230.345979-1-luiz.dentz@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+75 -25
+1 -1
include/net/bluetooth/hci_sync.h
··· 93 93 94 94 int hci_update_eir_sync(struct hci_dev *hdev); 95 95 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); 97 97 int hci_write_ssp_mode_sync(struct hci_dev *hdev, u8 mode); 98 98 99 99 int hci_get_random_address(struct hci_dev *hdev, bool require_privacy,
+41 -17
net/bluetooth/hci_conn.c
··· 149 149 150 150 hci_chan_list_flush(conn); 151 151 152 - hci_conn_hash_del(hdev, conn); 153 - 154 152 if (HCI_CONN_HANDLE_UNSET(conn->handle)) 155 153 ida_free(&hdev->unset_handle_ida, conn->handle); 156 154 ··· 1150 1152 disable_delayed_work_sync(&conn->auto_accept_work); 1151 1153 disable_delayed_work_sync(&conn->idle_work); 1152 1154 1153 - if (conn->type == ACL_LINK) { 1154 - /* Unacked frames */ 1155 - hdev->acl_cnt += conn->sent; 1156 - } else if (conn->type == LE_LINK) { 1157 - cancel_delayed_work(&conn->le_conn_timeout); 1155 + /* Remove the connection from the list so unacked logic can detect when 1156 + * a certain pool is not being utilized. 1157 + */ 1158 + hci_conn_hash_del(hdev, conn); 1158 1159 1159 - if (hdev->le_pkts) 1160 - hdev->le_cnt += conn->sent; 1160 + /* Handle unacked frames: 1161 + * 1162 + * - In case there are no connection, or if restoring the buffers 1163 + * considered in transist would overflow, restore all buffers to the 1164 + * pool. 1165 + * - Otherwise restore just the buffers considered in transit for the 1166 + * hci_conn 1167 + */ 1168 + switch (conn->type) { 1169 + case ACL_LINK: 1170 + if (!hci_conn_num(hdev, ACL_LINK) || 1171 + hdev->acl_cnt + conn->sent > hdev->acl_pkts) 1172 + hdev->acl_cnt = hdev->acl_pkts; 1161 1173 else 1162 1174 hdev->acl_cnt += conn->sent; 1163 - } else { 1164 - /* Unacked ISO frames */ 1165 - if (conn->type == CIS_LINK || 1166 - conn->type == BIS_LINK || 1167 - conn->type == PA_LINK) { 1168 - if (hdev->iso_pkts) 1169 - hdev->iso_cnt += conn->sent; 1170 - else if (hdev->le_pkts) 1175 + break; 1176 + case LE_LINK: 1177 + cancel_delayed_work(&conn->le_conn_timeout); 1178 + 1179 + if (hdev->le_pkts) { 1180 + if (!hci_conn_num(hdev, LE_LINK) || 1181 + hdev->le_cnt + conn->sent > hdev->le_pkts) 1182 + hdev->le_cnt = hdev->le_pkts; 1183 + else 1171 1184 hdev->le_cnt += conn->sent; 1185 + } else { 1186 + if ((!hci_conn_num(hdev, LE_LINK) && 1187 + !hci_conn_num(hdev, ACL_LINK)) || 1188 + hdev->acl_cnt + conn->sent > hdev->acl_pkts) 1189 + hdev->acl_cnt = hdev->acl_pkts; 1172 1190 else 1173 1191 hdev->acl_cnt += conn->sent; 1174 1192 } 1193 + break; 1194 + case CIS_LINK: 1195 + case BIS_LINK: 1196 + case PA_LINK: 1197 + if (!hci_iso_count(hdev) || 1198 + hdev->iso_cnt + conn->sent > hdev->iso_pkts) 1199 + hdev->iso_cnt = hdev->iso_pkts; 1200 + else 1201 + hdev->iso_cnt += conn->sent; 1202 + break; 1175 1203 } 1176 1204 1177 1205 skb_queue_purge(&conn->data_q);
+23 -2
net/bluetooth/hci_event.c
··· 2703 2703 if (!conn) 2704 2704 goto unlock; 2705 2705 2706 - if (status) { 2706 + if (status && status != HCI_ERROR_UNKNOWN_CONN_ID) { 2707 2707 mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 2708 2708 conn->dst_type, status); 2709 2709 ··· 2717 2717 2718 2718 goto done; 2719 2719 } 2720 + 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; 2720 2726 2721 2727 mgmt_conn = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags); 2722 2728 ··· 4404 4398 if (!conn) 4405 4399 continue; 4406 4400 4407 - conn->sent -= count; 4401 + /* Check if there is really enough packets outstanding before 4402 + * attempting to decrease the sent counter otherwise it could 4403 + * underflow.. 4404 + */ 4405 + if (conn->sent >= count) { 4406 + conn->sent -= count; 4407 + } else { 4408 + bt_dev_warn(hdev, "hcon %p sent %u < count %u", 4409 + conn, conn->sent, count); 4410 + conn->sent = 0; 4411 + } 4408 4412 4409 4413 for (i = 0; i < count; ++i) 4410 4414 hci_conn_tx_dequeue(conn); ··· 7024 7008 { 7025 7009 struct hci_evt_le_big_sync_lost *ev = data; 7026 7010 struct hci_conn *bis, *conn; 7011 + bool mgmt_conn; 7027 7012 7028 7013 bt_dev_dbg(hdev, "big handle 0x%2.2x", ev->handle); 7029 7014 ··· 7043 7026 while ((bis = hci_conn_hash_lookup_big_state(hdev, ev->handle, 7044 7027 BT_CONNECTED, 7045 7028 HCI_ROLE_SLAVE))) { 7029 + mgmt_conn = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &bis->flags); 7030 + mgmt_device_disconnected(hdev, &bis->dst, bis->type, bis->dst_type, 7031 + ev->reason, mgmt_conn); 7032 + 7046 7033 clear_bit(HCI_CONN_BIG_SYNC, &bis->flags); 7047 7034 hci_disconn_cfm(bis, ev->reason); 7048 7035 hci_conn_del(bis);
+3 -3
net/bluetooth/hci_sync.c
··· 3481 3481 return hci_write_scan_enable_sync(hdev, scan); 3482 3482 } 3483 3483 3484 - int hci_update_name_sync(struct hci_dev *hdev) 3484 + int hci_update_name_sync(struct hci_dev *hdev, const u8 *name) 3485 3485 { 3486 3486 struct hci_cp_write_local_name cp; 3487 3487 3488 3488 memset(&cp, 0, sizeof(cp)); 3489 3489 3490 - memcpy(cp.name, hdev->dev_name, sizeof(cp.name)); 3490 + memcpy(cp.name, name, sizeof(cp.name)); 3491 3491 3492 3492 return __hci_cmd_sync_status(hdev, HCI_OP_WRITE_LOCAL_NAME, 3493 3493 sizeof(cp), &cp, ··· 3540 3540 hci_write_fast_connectable_sync(hdev, false); 3541 3541 hci_update_scan_sync(hdev); 3542 3542 hci_update_class_sync(hdev); 3543 - hci_update_name_sync(hdev); 3543 + hci_update_name_sync(hdev, hdev->dev_name); 3544 3544 hci_update_eir_sync(hdev); 3545 3545 } 3546 3546
+7 -2
net/bluetooth/mgmt.c
··· 3892 3892 3893 3893 static int set_name_sync(struct hci_dev *hdev, void *data) 3894 3894 { 3895 + struct mgmt_pending_cmd *cmd = data; 3896 + struct mgmt_cp_set_local_name *cp = cmd->param; 3897 + 3895 3898 if (lmp_bredr_capable(hdev)) { 3896 - hci_update_name_sync(hdev); 3899 + hci_update_name_sync(hdev, cp->name); 3897 3900 hci_update_eir_sync(hdev); 3898 3901 } 3899 3902 ··· 9708 9705 if (!mgmt_connected) 9709 9706 return; 9710 9707 9711 - if (link_type != ACL_LINK && link_type != LE_LINK) 9708 + if (link_type != ACL_LINK && 9709 + link_type != LE_LINK && 9710 + link_type != BIS_LINK) 9712 9711 return; 9713 9712 9714 9713 bacpy(&ev.addr.bdaddr, bdaddr);