mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-04 20:19:47 +08:00
bluetooth pull request for net:
- hci_conn: Make unacked packet handling more robust - hci_event: Treat UNKNOWN_CONN_ID on disconnect as success - hci_event: Mark connection as closed during suspend disconnect - hci_event: Detect if HCI_EV_NUM_COMP_PKTS is unbalanced - hci_event: Disconnect device when BIG sync is lost - hci_sync: fix set_local_name race condition -----BEGIN PGP SIGNATURE----- iQJNBAABCgA3FiEE7E6oRXp8w05ovYr/9JCA4xAyCykFAmiosHUZHGx1aXoudm9u LmRlbnR6QGludGVsLmNvbQAKCRD0kIDjEDILKXtCD/92xuS5xvFhqhzexyXPyHa8 rNB8Gl9EpXlSkftmKwguRxo6LzM8U2R4zOx49MwCVFpcTdWYCP1WvDuWWKcmfuDg qyFIUyZWb8u02nRbscwN/yF0YcHwPXpAcWt8XmQvPu9sZ3i0dmJBSrabdZ+OI4oa Lqi4frdfWVFr46dpj9U61bWtY34lR+1BxWiOHtLT8+xGlgiugnXwkcwDY7bzmK6s hMabAoMCWv5iuWwE8LXubPYHg4M8PPrQORBQ/iNwJYtan7YD6f/sDd3rHlCF8cuU uvoCVXDx1UI7LrYsocb9iNHFsyvZD93W5xmK+8PAZKsMZgEcdfs3jLlT6zek/GI/ ab5nr6q+XVas3Z0tq3MblpAzRmlOZaLM97LqotQC4EBVyIH3JXhwN41nBDKycmM4 WBPWHZIsJ6ZIV+++tZIIuKAaZHSCiYcEwEiQyV06QdHoDfw9Wc39sr13IOqThXfv AOCwjnjUTuqZ6HnmogOcN87tYXQghJ12XJgNgFbxeoAtxqL1TDWtZKJkHB7oHY3l gGeN2ffRP+yoXPT7GWQoGAydKylf6fIPkRo64gbEoYmPy56djUZ2lnRMbrYm1MWR Yy4SaZhu84jLKdOsLxhRzZR2FxO3E568t2nDDA5xz2F4FkrP8/ih+fOO18+5UVK9 302cU7sOXc+aSt8LHP4lRQ== =4eUN -----END PGP SIGNATURE----- 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>
This commit is contained in:
commit
1559c9c231
@ -93,7 +93,7 @@ int hci_update_class_sync(struct hci_dev *hdev);
|
|||||||
|
|
||||||
int hci_update_eir_sync(struct hci_dev *hdev);
|
int hci_update_eir_sync(struct hci_dev *hdev);
|
||||||
int hci_update_class_sync(struct hci_dev *hdev);
|
int hci_update_class_sync(struct hci_dev *hdev);
|
||||||
int hci_update_name_sync(struct hci_dev *hdev);
|
int hci_update_name_sync(struct hci_dev *hdev, const u8 *name);
|
||||||
int hci_write_ssp_mode_sync(struct hci_dev *hdev, u8 mode);
|
int hci_write_ssp_mode_sync(struct hci_dev *hdev, u8 mode);
|
||||||
|
|
||||||
int hci_get_random_address(struct hci_dev *hdev, bool require_privacy,
|
int hci_get_random_address(struct hci_dev *hdev, bool require_privacy,
|
||||||
|
@ -149,8 +149,6 @@ static void hci_conn_cleanup(struct hci_conn *conn)
|
|||||||
|
|
||||||
hci_chan_list_flush(conn);
|
hci_chan_list_flush(conn);
|
||||||
|
|
||||||
hci_conn_hash_del(hdev, conn);
|
|
||||||
|
|
||||||
if (HCI_CONN_HANDLE_UNSET(conn->handle))
|
if (HCI_CONN_HANDLE_UNSET(conn->handle))
|
||||||
ida_free(&hdev->unset_handle_ida, conn->handle);
|
ida_free(&hdev->unset_handle_ida, conn->handle);
|
||||||
|
|
||||||
@ -1152,28 +1150,54 @@ void hci_conn_del(struct hci_conn *conn)
|
|||||||
disable_delayed_work_sync(&conn->auto_accept_work);
|
disable_delayed_work_sync(&conn->auto_accept_work);
|
||||||
disable_delayed_work_sync(&conn->idle_work);
|
disable_delayed_work_sync(&conn->idle_work);
|
||||||
|
|
||||||
if (conn->type == ACL_LINK) {
|
/* Remove the connection from the list so unacked logic can detect when
|
||||||
/* Unacked frames */
|
* a certain pool is not being utilized.
|
||||||
hdev->acl_cnt += conn->sent;
|
*/
|
||||||
} else if (conn->type == LE_LINK) {
|
hci_conn_hash_del(hdev, conn);
|
||||||
cancel_delayed_work(&conn->le_conn_timeout);
|
|
||||||
|
|
||||||
if (hdev->le_pkts)
|
/* Handle unacked frames:
|
||||||
hdev->le_cnt += conn->sent;
|
*
|
||||||
|
* - In case there are no connection, or if restoring the buffers
|
||||||
|
* considered in transist would overflow, restore all buffers to the
|
||||||
|
* pool.
|
||||||
|
* - Otherwise restore just the buffers considered in transit for the
|
||||||
|
* hci_conn
|
||||||
|
*/
|
||||||
|
switch (conn->type) {
|
||||||
|
case ACL_LINK:
|
||||||
|
if (!hci_conn_num(hdev, ACL_LINK) ||
|
||||||
|
hdev->acl_cnt + conn->sent > hdev->acl_pkts)
|
||||||
|
hdev->acl_cnt = hdev->acl_pkts;
|
||||||
else
|
else
|
||||||
hdev->acl_cnt += conn->sent;
|
hdev->acl_cnt += conn->sent;
|
||||||
} else {
|
break;
|
||||||
/* Unacked ISO frames */
|
case LE_LINK:
|
||||||
if (conn->type == CIS_LINK ||
|
cancel_delayed_work(&conn->le_conn_timeout);
|
||||||
conn->type == BIS_LINK ||
|
|
||||||
conn->type == PA_LINK) {
|
if (hdev->le_pkts) {
|
||||||
if (hdev->iso_pkts)
|
if (!hci_conn_num(hdev, LE_LINK) ||
|
||||||
hdev->iso_cnt += conn->sent;
|
hdev->le_cnt + conn->sent > hdev->le_pkts)
|
||||||
else if (hdev->le_pkts)
|
hdev->le_cnt = hdev->le_pkts;
|
||||||
|
else
|
||||||
hdev->le_cnt += conn->sent;
|
hdev->le_cnt += conn->sent;
|
||||||
|
} else {
|
||||||
|
if ((!hci_conn_num(hdev, LE_LINK) &&
|
||||||
|
!hci_conn_num(hdev, ACL_LINK)) ||
|
||||||
|
hdev->acl_cnt + conn->sent > hdev->acl_pkts)
|
||||||
|
hdev->acl_cnt = hdev->acl_pkts;
|
||||||
else
|
else
|
||||||
hdev->acl_cnt += conn->sent;
|
hdev->acl_cnt += conn->sent;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case CIS_LINK:
|
||||||
|
case BIS_LINK:
|
||||||
|
case PA_LINK:
|
||||||
|
if (!hci_iso_count(hdev) ||
|
||||||
|
hdev->iso_cnt + conn->sent > hdev->iso_pkts)
|
||||||
|
hdev->iso_cnt = hdev->iso_pkts;
|
||||||
|
else
|
||||||
|
hdev->iso_cnt += conn->sent;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
skb_queue_purge(&conn->data_q);
|
skb_queue_purge(&conn->data_q);
|
||||||
|
@ -2703,7 +2703,7 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
|
|||||||
if (!conn)
|
if (!conn)
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
|
||||||
if (status) {
|
if (status && status != HCI_ERROR_UNKNOWN_CONN_ID) {
|
||||||
mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
|
mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
|
||||||
conn->dst_type, status);
|
conn->dst_type, status);
|
||||||
|
|
||||||
@ -2718,6 +2718,12 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* During suspend, mark connection as closed immediately
|
||||||
|
* since we might not receive HCI_EV_DISCONN_COMPLETE
|
||||||
|
*/
|
||||||
|
if (hdev->suspended)
|
||||||
|
conn->state = BT_CLOSED;
|
||||||
|
|
||||||
mgmt_conn = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags);
|
mgmt_conn = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags);
|
||||||
|
|
||||||
if (conn->type == ACL_LINK) {
|
if (conn->type == ACL_LINK) {
|
||||||
@ -4398,7 +4404,17 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data,
|
|||||||
if (!conn)
|
if (!conn)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
conn->sent -= count;
|
/* Check if there is really enough packets outstanding before
|
||||||
|
* attempting to decrease the sent counter otherwise it could
|
||||||
|
* underflow..
|
||||||
|
*/
|
||||||
|
if (conn->sent >= count) {
|
||||||
|
conn->sent -= count;
|
||||||
|
} else {
|
||||||
|
bt_dev_warn(hdev, "hcon %p sent %u < count %u",
|
||||||
|
conn, conn->sent, count);
|
||||||
|
conn->sent = 0;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < count; ++i)
|
for (i = 0; i < count; ++i)
|
||||||
hci_conn_tx_dequeue(conn);
|
hci_conn_tx_dequeue(conn);
|
||||||
@ -7008,6 +7024,7 @@ static void hci_le_big_sync_lost_evt(struct hci_dev *hdev, void *data,
|
|||||||
{
|
{
|
||||||
struct hci_evt_le_big_sync_lost *ev = data;
|
struct hci_evt_le_big_sync_lost *ev = data;
|
||||||
struct hci_conn *bis, *conn;
|
struct hci_conn *bis, *conn;
|
||||||
|
bool mgmt_conn;
|
||||||
|
|
||||||
bt_dev_dbg(hdev, "big handle 0x%2.2x", ev->handle);
|
bt_dev_dbg(hdev, "big handle 0x%2.2x", ev->handle);
|
||||||
|
|
||||||
@ -7026,6 +7043,10 @@ static void hci_le_big_sync_lost_evt(struct hci_dev *hdev, void *data,
|
|||||||
while ((bis = hci_conn_hash_lookup_big_state(hdev, ev->handle,
|
while ((bis = hci_conn_hash_lookup_big_state(hdev, ev->handle,
|
||||||
BT_CONNECTED,
|
BT_CONNECTED,
|
||||||
HCI_ROLE_SLAVE))) {
|
HCI_ROLE_SLAVE))) {
|
||||||
|
mgmt_conn = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &bis->flags);
|
||||||
|
mgmt_device_disconnected(hdev, &bis->dst, bis->type, bis->dst_type,
|
||||||
|
ev->reason, mgmt_conn);
|
||||||
|
|
||||||
clear_bit(HCI_CONN_BIG_SYNC, &bis->flags);
|
clear_bit(HCI_CONN_BIG_SYNC, &bis->flags);
|
||||||
hci_disconn_cfm(bis, ev->reason);
|
hci_disconn_cfm(bis, ev->reason);
|
||||||
hci_conn_del(bis);
|
hci_conn_del(bis);
|
||||||
|
@ -3481,13 +3481,13 @@ int hci_update_scan_sync(struct hci_dev *hdev)
|
|||||||
return hci_write_scan_enable_sync(hdev, scan);
|
return hci_write_scan_enable_sync(hdev, scan);
|
||||||
}
|
}
|
||||||
|
|
||||||
int hci_update_name_sync(struct hci_dev *hdev)
|
int hci_update_name_sync(struct hci_dev *hdev, const u8 *name)
|
||||||
{
|
{
|
||||||
struct hci_cp_write_local_name cp;
|
struct hci_cp_write_local_name cp;
|
||||||
|
|
||||||
memset(&cp, 0, sizeof(cp));
|
memset(&cp, 0, sizeof(cp));
|
||||||
|
|
||||||
memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
|
memcpy(cp.name, name, sizeof(cp.name));
|
||||||
|
|
||||||
return __hci_cmd_sync_status(hdev, HCI_OP_WRITE_LOCAL_NAME,
|
return __hci_cmd_sync_status(hdev, HCI_OP_WRITE_LOCAL_NAME,
|
||||||
sizeof(cp), &cp,
|
sizeof(cp), &cp,
|
||||||
@ -3540,7 +3540,7 @@ int hci_powered_update_sync(struct hci_dev *hdev)
|
|||||||
hci_write_fast_connectable_sync(hdev, false);
|
hci_write_fast_connectable_sync(hdev, false);
|
||||||
hci_update_scan_sync(hdev);
|
hci_update_scan_sync(hdev);
|
||||||
hci_update_class_sync(hdev);
|
hci_update_class_sync(hdev);
|
||||||
hci_update_name_sync(hdev);
|
hci_update_name_sync(hdev, hdev->dev_name);
|
||||||
hci_update_eir_sync(hdev);
|
hci_update_eir_sync(hdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3892,8 +3892,11 @@ static void set_name_complete(struct hci_dev *hdev, void *data, int err)
|
|||||||
|
|
||||||
static int set_name_sync(struct hci_dev *hdev, void *data)
|
static int set_name_sync(struct hci_dev *hdev, void *data)
|
||||||
{
|
{
|
||||||
|
struct mgmt_pending_cmd *cmd = data;
|
||||||
|
struct mgmt_cp_set_local_name *cp = cmd->param;
|
||||||
|
|
||||||
if (lmp_bredr_capable(hdev)) {
|
if (lmp_bredr_capable(hdev)) {
|
||||||
hci_update_name_sync(hdev);
|
hci_update_name_sync(hdev, cp->name);
|
||||||
hci_update_eir_sync(hdev);
|
hci_update_eir_sync(hdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -9705,7 +9708,9 @@ void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
|||||||
if (!mgmt_connected)
|
if (!mgmt_connected)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (link_type != ACL_LINK && link_type != LE_LINK)
|
if (link_type != ACL_LINK &&
|
||||||
|
link_type != LE_LINK &&
|
||||||
|
link_type != BIS_LINK)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bacpy(&ev.addr.bdaddr, bdaddr);
|
bacpy(&ev.addr.bdaddr, bdaddr);
|
||||||
|
Loading…
Reference in New Issue
Block a user