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@xxxxxx> --- 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