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 <[email protected]>
---
Notes:
v2: new patch
net/bluetooth/hci_sync.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
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)
--
2.41.0