diff mbox series

[v2,3/4] Bluetooth: hci_sync: disconnect linked connections before parents

Message ID 89fd73eb453f951438c594222828aafe8e4640a3.1691352503.git.pav@iki.fi (mailing list archive)
State New, archived
Headers show
Series [v2,1/4] Bluetooth: hci_sync: fix canceling LE scanning / CIS create conn state | expand

Checks

Context Check Description
tedd_an/pre-ci_am success Success
tedd_an/CheckPatch success CheckPatch PASS
tedd_an/GitLint success Gitlint PASS
tedd_an/SubjectPrefix success Gitlint PASS
tedd_an/IncrementalBuild success Incremental Build PASS

Commit Message

Pauli Virtanen Aug. 6, 2023, 8:18 p.m. UTC
SCO/ISO connections are disconnected implicitly if the ACL connection is
gone.  If we disconnect ACL first, controller may error disconnecting
ISO/SCO, which in hci_disconnect_all_sync fails powering off.  With ISO
connections present, powering off usually fails because of this.

Fix by aborting linked connections first in hci_disconnect_all_sync.

Signed-off-by: Pauli Virtanen <pav@iki.fi>
---

Notes:
    v2: new patch

 net/bluetooth/hci_sync.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
diff mbox series

Patch

diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
index 228259f44815..a476594ecd2a 100644
--- a/net/bluetooth/hci_sync.c
+++ b/net/bluetooth/hci_sync.c
@@ -5435,10 +5435,26 @@  static int hci_disconnect_all_sync(struct hci_dev *hdev, u8 reason)
 	do {
 		conn = NULL;
 		list_for_each_entry_rcu(c, &hdev->conn_hash.list, list) {
+			struct hci_link *link;
+
 			if (c->abort_reason == reason)
 				continue;
 
 			conn = c;
+
+			/* Abort linked connections first. Disconnecting ACL
+			 * implicitly disconnects SCO/ISO, and controller may
+			 * error commands disconnecting them after ACL.
+			 * (See Core v5.4 Vol 4 Part E Sec 7.1.6)
+			 */
+			if (conn->parent)
+				break;
+			list_for_each_entry_rcu(link, &conn->link_list, list) {
+				if (link->conn->abort_reason != reason) {
+					conn = link->conn;
+					break;
+				}
+			}
 			break;
 		}
 		if (!conn)