mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-04 20:19:47 +08:00
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: 5638d9ea9c
("Bluetooth: hci_conn: Fix not restoring ISO buffer count on disconnect")
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
parent
01b9128c5d
commit
5d7eba62e5
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user