Skip to content

Commit 7af23ab

Browse files
Vudentzgregkh
authored andcommitted
Bluetooth: hci_conn: Make unacked packet handling more robust
[ Upstream commit 5d7eba6 ] 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 <luiz.von.dentz@intel.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 775fe69 commit 7af23ab

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

@@ -1142,28 +1140,54 @@ void hci_conn_del(struct hci_conn *conn)
11421140
disable_delayed_work_sync(&conn->auto_accept_work);
11431141
disable_delayed_work_sync(&conn->idle_work);
11441142

1145-
if (conn->type == ACL_LINK) {
1146-
/* Unacked frames */
1147-
hdev->acl_cnt += conn->sent;
1148-
} else if (conn->type == LE_LINK) {
1149-
cancel_delayed_work(&conn->le_conn_timeout);
1143+
/* Remove the connection from the list so unacked logic can detect when
1144+
* a certain pool is not being utilized.
1145+
*/
1146+
hci_conn_hash_del(hdev, conn);
11501147

1151-
if (hdev->le_pkts)
1152-
hdev->le_cnt += conn->sent;
1148+
/* Handle unacked frames:
1149+
*
1150+
* - In case there are no connection, or if restoring the buffers
1151+
* considered in transist would overflow, restore all buffers to the
1152+
* pool.
1153+
* - Otherwise restore just the buffers considered in transit for the
1154+
* hci_conn
1155+
*/
1156+
switch (conn->type) {
1157+
case ACL_LINK:
1158+
if (!hci_conn_num(hdev, ACL_LINK) ||
1159+
hdev->acl_cnt + conn->sent > hdev->acl_pkts)
1160+
hdev->acl_cnt = hdev->acl_pkts;
11531161
else
11541162
hdev->acl_cnt += conn->sent;
1155-
} else {
1156-
/* Unacked ISO frames */
1157-
if (conn->type == CIS_LINK ||
1158-
conn->type == BIS_LINK ||
1159-
conn->type == PA_LINK) {
1160-
if (hdev->iso_pkts)
1161-
hdev->iso_cnt += conn->sent;
1162-
else if (hdev->le_pkts)
1163+
break;
1164+
case LE_LINK:
1165+
cancel_delayed_work(&conn->le_conn_timeout);
1166+
1167+
if (hdev->le_pkts) {
1168+
if (!hci_conn_num(hdev, LE_LINK) ||
1169+
hdev->le_cnt + conn->sent > hdev->le_pkts)
1170+
hdev->le_cnt = hdev->le_pkts;
1171+
else
11631172
hdev->le_cnt += conn->sent;
1173+
} else {
1174+
if ((!hci_conn_num(hdev, LE_LINK) &&
1175+
!hci_conn_num(hdev, ACL_LINK)) ||
1176+
hdev->acl_cnt + conn->sent > hdev->acl_pkts)
1177+
hdev->acl_cnt = hdev->acl_pkts;
11641178
else
11651179
hdev->acl_cnt += conn->sent;
11661180
}
1181+
break;
1182+
case CIS_LINK:
1183+
case BIS_LINK:
1184+
case PA_LINK:
1185+
if (!hci_iso_count(hdev) ||
1186+
hdev->iso_cnt + conn->sent > hdev->iso_pkts)
1187+
hdev->iso_cnt = hdev->iso_pkts;
1188+
else
1189+
hdev->iso_cnt += conn->sent;
1190+
break;
11671191
}
11681192

11691193
skb_queue_purge(&conn->data_q);

0 commit comments

Comments
 (0)