Skip to content

Commit 5d7eba6

Browse files
committed
Bluetooth: hci_conn: Make unacked packet handling more robust
This attempts to make unacked packet handling more robust by detecting if there are no connections left then restore all buffers of the respective pool. Fixes: 5638d9e ("Bluetooth: hci_conn: Fix not restoring ISO buffer count on disconnect") Signed-off-by: Luiz Augusto von Dentz <[email protected]>
1 parent 01b9128 commit 5d7eba6

File tree

1 file changed

+41
-17
lines changed

1 file changed

+41
-17
lines changed

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);

0 commit comments

Comments
 (0)