[PATCH v3 5/6] Bluetooth: Unlink CISes when LE disconnects in hci_conn_del

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Currently, hci_conn_del calls hci_conn_unlink for BR/EDR, (e)SCO, and
CIS connections, i.e., everything except LE connections. However, if
(e)SCO connections are unlinked when BR/EDR disconnects, CIS connections
should also be unlinked when LE disconnects.

In terms of disconnection behavior, CIS and (e)SCO connections are not
too different. One peculiarity of CIS is that when CIS connections are
disconnected, the CIS handle isn't deleted, as per [BLUETOOTH CORE
SPECIFICATION Version 5.4 | Vol 4, Part E] 7.1.6 Disconnect command:

	All SCO, eSCO, and CIS connections on a physical link should be
	disconnected before the ACL connection on the same physical
	connection is disconnected. If it does not, they will be
	implicitly disconnected as part of the ACL disconnection.
	...
	Note: As specified in Section 7.7.5, on the Central, the handle
	for a CIS remains valid even after disconnection and, therefore,
	the Host can recreate a disconnected CIS at a later point in
	time using the same connection handle.

This peculiarity has nothing to do with the code, as long as the current
implementation always ties the CIS handle, the CIS connection, and the
LE connection together in hci_link, and manually performs CIS deletion
in cis_cleanup after CIS disconnections.

Signed-off-by: Ruihan Li <lrh2000@xxxxxxxxxx>
---
 net/bluetooth/hci_conn.c | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index e76ebb50d..de553e062 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -1092,7 +1092,9 @@ static void hci_conn_unlink(struct hci_conn *conn)
 			 * yet at this point. Delete it now, otherwise it is
 			 * possible for it to be stuck and can't be deleted.
 			 */
-			if (child->handle == HCI_CONN_HANDLE_UNSET)
+			if ((child->type == SCO_LINK ||
+			     child->type == ESCO_LINK) &&
+			    child->handle == HCI_CONN_HANDLE_UNSET)
 				hci_conn_del(child);
 		}
 
@@ -1119,11 +1121,17 @@ void hci_conn_del(struct hci_conn *conn)
 
 	BT_DBG("%s hcon %p handle %d", hdev->name, conn, conn->handle);
 
+	hci_conn_unlink(conn);
+
+	/* hci_conn_unlink may trigger additional disc_work, so
+	 * ensure to perform cancelling after that.
+	 */
+	cancel_delayed_work_sync(&conn->disc_work);
+
 	cancel_delayed_work_sync(&conn->auto_accept_work);
 	cancel_delayed_work_sync(&conn->idle_work);
 
 	if (conn->type == ACL_LINK) {
-		hci_conn_unlink(conn);
 		/* Unacked frames */
 		hdev->acl_cnt += conn->sent;
 	} else if (conn->type == LE_LINK) {
@@ -1134,8 +1142,6 @@ void hci_conn_del(struct hci_conn *conn)
 		else
 			hdev->acl_cnt += conn->sent;
 	} else {
-		hci_conn_unlink(conn);
-
 		/* Unacked ISO frames */
 		if (conn->type == ISO_LINK) {
 			if (hdev->iso_pkts)
@@ -1147,11 +1153,6 @@ void hci_conn_del(struct hci_conn *conn)
 		}
 	}
 
-	/* hci_conn_unlink may trigger additional disc_work, so
-	 * ensure to perform cancelling after that.
-	 */
-	cancel_delayed_work_sync(&conn->disc_work);
-
 	if (conn->amp_mgr)
 		amp_mgr_put(conn->amp_mgr);
 
-- 
2.40.0




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux