All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/6] Bluetooth: Fix SCO setup failures after an abandoned setup
@ 2026-10-08 22:26 Hitalo Souza
  2026-10-08 22:26 ` [PATCH v3 1/6] Bluetooth: hci_event: Don't fail a connected SCO link on setup errors Hitalo Souza
                   ` (6 more replies)
  0 siblings, 7 replies; 9+ messages in thread
From: Hitalo Souza @ 2026-10-08 22:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, luiz.dentz, linux-kernel, Hitalo Souza

Since commit a13f316e90fd ("Bluetooth: hci_conn: Consolidate code for
aborting connections"), closing a SCO socket while its setup is pending
deletes the hci_conn, after a Create Connection Cancel that cannot
cancel a synchronous connection. When a new socket connects right away,
e.g. PipeWire recreating the HFP transport after a codec negotiation as
in bluez/bluez#2562, the abandoned setup can still complete, and:

 1. It is matched to the new connection by address, the controller then
    rejects the new connection's own setup, and the rejection handler
    fails the first link on the ACL, which is now the connected one,
    without disconnecting it (patch 1).

 2. It is matched to the new connection before that connection's own
    setup was sent: Enhanced Setup Synchronous Connection goes through
    the cmd_sync queue, and any setup waits for the ACL to leave sniff
    mode. The setup is then sent anyway and rejected. This is the order
    of events in the report (patch 2).

 3. Nothing takes it over, or it is a second link for a connection
    that is already up: the link stays up in the controller with no
    connection for it, and the controller rejects every further setup
    for the device until the ACL drops (patch 4).

Patches 3 and 5 make links that complete for an aborted connection be
disconnected in general, as Luiz suggested, not only SCO ones. Patch 3:
a link (ACL, SCO/eSCO or LE) that completes while its connection is
being aborted, which then refuses the handle since 16e3b6429159
("Bluetooth: hci_conn: Fix modifying handle while aborting") and, for
LE, 181a42edddf5 ("Bluetooth: Make handle of hci_conn be unique").
Patch 5: an incoming ACL connection aborted after it was accepted,
which is deleted before its link completes. Patch 6 stops notifying
the driver of the air mode of a SCO link that did not come up: with
btusb, that notification and the one for the connection's deletion
right after could stop the audio of another SCO connection. btusb can
still do that when a SCO link that was up goes down while another one
stays up; that is not changed here.

In 1 and 2 the new connection keeps the link of the abandoned setup,
with the parameters of that setup: the completion event does not say
which setup it belongs to. Its Air_Mode would show a change between
CVSD and transparent data, but the series does not act on it. An
abandoned setup that fails after a new connection was made, in Command
Status or in its completion event, is likewise applied to that
connection. Before a13f316e90fd both happened in another way, as the
next socket reused the pending hci_conn.

If a controller answers the setup of a SCO_LINK connection (only SCO
packet types allowed, e.g. with the disable_esco parameter of sco.c)
with an eSCO link, that link was ignored, so the connect timed out and
the link stayed up. Patch 4 now lets the connection take it, as an
eSCO connection already takes a SCO link.

Changes in v3:
- Patch 4: a SCO_LINK connection takes an eSCO link that answers its
  setup, instead of the link being ignored and left up (Sashiko). T6
  now checks that the connection gets the link.
- Patch 1: the commit message notes that a Command Status does not
  tell which setup failed, which the patch does not change (Sashiko).
- Rebased on bluetooth-next 97a128698d9d, without conflicts.
- Tests for BlueZ's sco-tester and l2cap-tester that abort a connection
  while its connection complete event is pending, as Luiz asked:
  https://lore.kernel.org/linux-bluetooth/20261008215756.2710812-1-enghitalo@gmail.com/
- v2: https://lore.kernel.org/linux-bluetooth/20261008151238.2138665-1-enghitalo@gmail.com/

Changes in v2:
- New patch 3, following Luiz's review: disconnect any link that
  completes while its connection is being aborted, on Connection
  Complete, Synchronous Connection Complete and LE Connection Complete.
  It replaces the SCO-only handling of that case in v1's patch 3, and
  covers the ACL and LE cases Sashiko pointed out.
- Patch 4 (v1's patch 3) uses the helper of patch 3, and also
  disconnects a second SCO link that completes with Connection Complete
  for a connection that is already up (Sashiko).
- New patch 5: disconnect an ACL link that completes after its
  connection was aborted and deleted (an incoming connection).
- New patch 6: notify the driver of the air mode only of a SCO link
  that came up (Sashiko).
- The disable_esco case is described as what it is: a controller
  answering a SCO-only setup with an eSCO link.
- New tests T5b, T7, T8 and T9.
- v1: https://lore.kernel.org/linux-bluetooth/20261007154353.148223-1-enghitalo@gmail.com/

Patch 2 relies on hci_enhanced_setup_sync() taking hdev->lock, since
024e05f73a4c ("Bluetooth: hci_conn: Lock parent access during enhanced
SCO setup"); a backport to a kernel without that commit needs the lock
taken around the new checks.

Testing:

- QEMU/KVM, bluetooth-next at 97a128698d9d and with each patch applied
  in turn, x86_64 defconfig + kvm_guest.config + BT=y, BT_HCIVHCI=y. A
  userspace program emulates the controller and the headset over
  hci_vhci; the controller allows one eSCO link per ACL and rejects
  further setups with 0x0a (0x12 in T1, as in the report), except in
  T5, where it allows a second one. Each case was run over Setup
  Synchronous Connection (L), Enhanced Setup Synchronous Connection (E)
  and Add SCO Connection (A, controller without eSCO):

  T0  connect, receive SCO data, close
  T1  close a socket with its setup pending, connect a new one; the
      first setup completes, then the new one is rejected
  T1b like T1, but the first setup completes before the new one is
      sent, which waits for the ACL to leave sniff mode
  T1c like T1b, but the new setup waits in the cmd_sync queue (E only)
  T2  close a socket with its setup pending, the setup completes
      afterwards, connect a new socket (cancel answered 0x0b and 0x02)
  T2b like T2, but the setup completes while the abort still waits in
      the cmd_sync queue
  T3  a setup rejected with 0x0d in Command Status
  T4  like T2, but the abandoned setup completes with 0x22
  T5  like T1, but the new setup completes too, with a second link
  T5b an incoming SCO connection is up, and a second SCO link to the
      device completes with Connection Complete (A only)
  T6  disable_esco set, and the emulated controller answers the
      SCO-only setup with an eSCO link (L and E): the connection gets
      the link, receives SCO data and disconnects it when closed
  T7  an ACL connect to another device is aborted while paging, and
      the page succeeds as Create Connection Cancel arrives (cancel
      answered 0x0b)
  T8  with an emulated LE-only controller: an L2CAP LE connect is
      aborted while LE Create Connection is pending, and the connection
      completes as LE Create Connection Cancel arrives (cancel answered
      0x0c); also with the cancel succeeding in time, where nothing may
      be disconnected
  T9  an incoming ACL connection is aborted with MGMT_OP_DISCONNECT
      after it was accepted; Create Connection Cancel fails with 0x02,
      then the link completes

  In T1c the cmd_sync queue waits for a Read RSSI (from mgmt Get
  Connection Information) that the emulator leaves unanswered; in T2b
  it waits for an ACL connection to another device, whose Connection
  Complete the emulator holds as during a page.

                  T1   T1b  T1c  T2   T2b  T5   T5b  T6   T7   T8   T9
  bluetooth-next  FAIL FAIL FAIL FAIL FAIL FAIL FAIL FAIL FAIL FAIL FAIL
  + patch 1       pass FAIL FAIL FAIL FAIL FAIL FAIL FAIL FAIL FAIL FAIL
  + patches 1-2   pass (*)  pass FAIL FAIL FAIL FAIL FAIL FAIL FAIL FAIL
  + patches 1-3   pass (*)  pass FAIL pass FAIL FAIL FAIL pass pass FAIL
  + patches 1-4   pass pass pass pass pass pass pass pass pass pass FAIL
  + patches 1-5   pass pass pass pass pass pass pass pass pass pass pass
  + patches 1-6   pass pass pass pass pass pass pass pass pass pass pass

  T0, T3, T4 and the LE connect cancelled in time pass on every row.

  The results are the same on L, E and A, except (*): pass on L and E,
  FAIL on A, where the abandoned link is not taken over by a connection
  that has not started its setup, and stays up until patch 4.

  Without the series, the new socket gets EINVAL in T1 (the emulator
  rejects with 0x12) and EMLINK in T1b and T1c (its duplicate setup is
  rejected with 0x0a), the next connect gets EMLINK in T2 and T2b, and
  the second links in T5 and T5b and the ACL and LE links in T7, T8 and
  T9 are not disconnected (they stay up until the ACL drops, or for
  good); in T6 the connect times out and the link stays up. With it,
  the new sockets and the connection in T6 receive SCO data and no
  Create Connection Cancel is sent for SCO; the links that nothing
  takes over (T1b on A, T2, T2b, T7, T8, T9) and the second links in T5
  and T5b are disconnected as soon as they complete, and T4 and the LE
  connect cancelled in time send no Disconnect. No kernel warnings.
  Patch 6 is not covered here, as hci_vhci has no notify callback.

- BlueZ testers (master 866b0b8 with the new tests) in the same VM, on
  the debug kernel below plus CRYPTO_USER_API_{HASH,SKCIPHER}, run
  twice: with the series sco-tester (31), l2cap-tester (113) and
  iso-tester (141) pass, and without it only the three new tests fail.
  mgmt-tester has 8 to 10 LL Privacy failures of 506 per run, with and
  without the series.

- Real hardware, with v2 (v3 only changes what happens when a SCO_LINK
  connection gets an eSCO link, which does not occur there): a MediaTek
  MT7921 (USB 04ca:3802, legacy Setup Synchronous Connection because of
  HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN) with a Sony WF-1000XM6, on
  v7.1.13 with the series built as the bluetooth module (patch 2 needs
  one change there, as hci_enhanced_setup_sync() does not take
  hdev->lock in that version; the other functions touched are the same
  as in bluetooth-next). With PipeWire 1.6.8 the abandoned setups were
  first seen there: Create Connection Cancel was answered with Unknown
  Connection Identifier, and the setup still completed afterwards.

  A SCO socket was closed 150 ms into its setup and a new one connected
  0.3 s or 2.5 s later, five times; each abandoned setup completed about
  0.2 s after it started, before the new connect. Without the series the
  first abandoned link after each ACL connect (two in the run) was left
  up, and from then on the controller rejected every setup, plain
  connects included, with Unsupported LMP Parameter Value (0x20) until
  the ACL was dropped. With the series no Create Connection Cancel was
  sent, each abandoned link was disconnected as soon as it completed,
  and every new socket and the plain connects after them received SCO
  data. An abandoned setup that failed (the headset rejects CVSD with
  0x20) caused no Disconnect. Between the groups PipeWire switched the
  headset from A2DP to HFP (mSBC) for a recording while I counted
  aloud: speech was recorded all three times, with and without the
  series. The cases of patches 1 and 2 did not occur there.

- W=1 builds of net/bluetooth/ and drivers/bluetooth/, no warnings:
  GCC 16.2.1 x86_64 allmodconfig and i386 defconfig, LLVM 22.1.8 arm64
  defconfig, arm multi_v7_defconfig, riscv defconfig and powerpc
  ppc64_defconfig (big-endian), with BT, BT_HCIBTUSB{,_MTK,_QCOM} and
  BT_VIRTIO.

- sparse v0.6.5-rc1 on the same directories: the same 16 reports with
  and without the series, none on the lines touched here.

- With the series, the same tests on a kernel with PROVE_LOCKING,
  PROVE_RCU, KASAN, DEBUG_ATOMIC_SLEEP, DEBUG_LIST and
  DEBUG_OBJECTS{,_WORK,_TIMERS} enabled: all pass on the three paths
  and with the LE-only controller, with no lockdep, KASAN or
  debugobjects reports, also while the BlueZ testers ran.

The patches, the commit messages, this letter and the test programs
were prepared with an AI assistant (see the Assisted-by tags), which
reproduced the report in the emulator and wrote and tested the fixes;
the real-hardware runs were done on my laptop with my headset.

Hitalo Souza (6):
  Bluetooth: hci_event: Don't fail a connected SCO link on setup errors
  Bluetooth: hci_conn: Don't set up a SCO link that is already up
  Bluetooth: hci_event: Disconnect links that complete while being
    aborted
  Bluetooth: Don't leave abandoned SCO links up in the controller
  Bluetooth: hci_event: Disconnect an ACL link that completes after its
    abort
  Bluetooth: hci_event: Notify the driver only of SCO links that came up

 net/bluetooth/hci_conn.c  |  24 +++++++-
 net/bluetooth/hci_event.c | 124 ++++++++++++++++++++++++++++++++------
 net/bluetooth/hci_sync.c  |   8 +++
 3 files changed, 135 insertions(+), 21 deletions(-)


base-commit: 97a128698d9dcacb9a15cdc5080718a644b12637
-- 
2.55.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v3 1/6] Bluetooth: hci_event: Don't fail a connected SCO link on setup errors
  2026-10-08 22:26 [PATCH v3 0/6] Bluetooth: Fix SCO setup failures after an abandoned setup Hitalo Souza
@ 2026-10-08 22:26 ` Hitalo Souza
  2026-10-09  1:11   ` Bluetooth: Fix SCO setup failures after an abandoned setup bluez.test.bot
  2026-10-08 22:26 ` [PATCH v3 2/6] Bluetooth: hci_conn: Don't set up a SCO link that is already up Hitalo Souza
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 9+ messages in thread
From: Hitalo Souza @ 2026-10-08 22:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, luiz.dentz, linux-kernel, Hitalo Souza

When Add SCO Connection, Setup Synchronous Connection or Enhanced Setup
Synchronous Connection fails in Command Status, the error handlers fail
the first link on the ACL, whatever its state. If that link is already
up, it is deleted while the controller keeps it: its socket gets an
error and, as no Disconnect is sent, later setups to the device are
rejected until the ACL drops.

A link that is up can be the first one on the ACL since commit
a13f316e90fd ("Bluetooth: hci_conn: Consolidate code for aborting
connections"). Aborting a pending SCO/eSCO setup, e.g. because its
socket was closed, now deletes its hci_conn, so a socket that connects
right after gets a new one and sends its own setup. The abandoned setup
can still complete, and it is then matched to the new connection by
address. When the controller rejects the new setup because a link
already exists, the handler fails the connection that just came up.
This was reported with an HFP headset, where the rejection was Invalid
HCI Command Parameters and the microphone stayed silent.

Only fail a link that is still waiting for its setup to complete. A
Command Status does not tell which setup it is for, so, as before, when
a connection is aborted while its setup is pending and another one then
starts a setup on the ACL, an error for the first setup fails the
second connection.

Link: https://github.com/bluez/bluez/issues/2562
Fixes: a13f316e90fd ("Bluetooth: hci_conn: Consolidate code for aborting connections")
Assisted-by: LLM
Signed-off-by: Hitalo Souza <enghitalo@gmail.com>
---
 net/bluetooth/hci_event.c | 24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index c055d16cf..cbe53e19e 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2400,13 +2400,19 @@ static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
 
 	acl = hci_conn_hash_lookup_handle(hdev, handle);
 	if (acl) {
-		link = list_first_entry_or_null(&acl->link_list,
-						struct hci_link, list);
-		if (link && link->conn) {
+		/* Only a link still waiting for its setup can be the one the
+		 * failed command was for: one that is already up must be kept.
+		 */
+		list_for_each_entry(link, &acl->link_list, list) {
+			if (link->conn->state != BT_CONNECT ||
+			    !HCI_CONN_HANDLE_UNSET(link->conn->handle))
+				continue;
+
 			link->conn->state = BT_CLOSED;
 
 			hci_connect_cfm(link->conn, status);
 			hci_conn_del(link->conn);
+			break;
 		}
 	}
 
@@ -2683,13 +2689,19 @@ static void hci_setup_sync_conn_status(struct hci_dev *hdev, __u16 handle,
 
 	acl = hci_conn_hash_lookup_handle(hdev, handle);
 	if (acl) {
-		link = list_first_entry_or_null(&acl->link_list,
-						struct hci_link, list);
-		if (link && link->conn) {
+		/* Only a link still waiting for its setup can be the one the
+		 * failed command was for: one that is already up must be kept.
+		 */
+		list_for_each_entry(link, &acl->link_list, list) {
+			if (link->conn->state != BT_CONNECT ||
+			    !HCI_CONN_HANDLE_UNSET(link->conn->handle))
+				continue;
+
 			link->conn->state = BT_CLOSED;
 
 			hci_connect_cfm(link->conn, status);
 			hci_conn_del(link->conn);
+			break;
 		}
 	}
 
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v3 2/6] Bluetooth: hci_conn: Don't set up a SCO link that is already up
  2026-10-08 22:26 [PATCH v3 0/6] Bluetooth: Fix SCO setup failures after an abandoned setup Hitalo Souza
  2026-10-08 22:26 ` [PATCH v3 1/6] Bluetooth: hci_event: Don't fail a connected SCO link on setup errors Hitalo Souza
@ 2026-10-08 22:26 ` Hitalo Souza
  2026-10-08 22:26 ` [PATCH v3 3/6] Bluetooth: hci_event: Disconnect links that complete while being aborted Hitalo Souza
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Hitalo Souza @ 2026-10-08 22:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, luiz.dentz, linux-kernel, Hitalo Souza

Since commit a13f316e90fd ("Bluetooth: hci_conn: Consolidate code for
aborting connections"), a SCO/eSCO setup abandoned while pending can
complete after a new connection to the same device was made, and it is
then matched to that connection by address. The new connection's own
setup may not have been sent yet at that point: Enhanced Setup
Synchronous Connection is sent later from the cmd_sync queue, and any
setup is deferred while the ACL leaves sniff mode. When it runs, it
sets the connection back to BT_CONNECT and sends a second setup, which
the controller rejects since a link already exists. The connection that
is up is then failed by the rejection, or left in BT_CONNECT and later
deleted without a Disconnect when its socket is closed.

This is the order of events in the report: the second Enhanced Setup
Synchronous Connection was sent after the first setup had completed,
and was rejected with Invalid HCI Command Parameters.

Don't send a setup for a connection that already has a handle. In
hci_enhanced_setup_sync(), take hdev->lock before checking that, and
check under it that the connection still exists, as
configure_datapath_sync() runs without the lock.

Closes: https://github.com/bluez/bluez/issues/2562
Fixes: a13f316e90fd ("Bluetooth: hci_conn: Consolidate code for aborting connections")
Assisted-by: LLM
Signed-off-by: Hitalo Souza <enghitalo@gmail.com>
---
 net/bluetooth/hci_conn.c | 24 ++++++++++++++++++++++--
 1 file changed, 22 insertions(+), 2 deletions(-)

diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 29da3fe2b..399c7db77 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -290,6 +290,22 @@ static int hci_enhanced_setup_sync(struct hci_dev *hdev, void *data)
 
 	configure_datapath_sync(hdev, &conn->codec);
 
+	hci_dev_lock(hdev);
+
+	/* configure_datapath_sync() runs without the lock */
+	if (!hci_conn_valid(hdev, conn)) {
+		hci_dev_unlock(hdev);
+		return -ECANCELED;
+	}
+
+	/* The link may have come up while this was queued, see
+	 * hci_sco_setup().
+	 */
+	if (!HCI_CONN_HANDLE_UNSET(conn->handle)) {
+		hci_dev_unlock(hdev);
+		return 0;
+	}
+
 	conn->state = BT_CONNECT;
 	conn->out = true;
 
@@ -302,8 +318,6 @@ static int hci_enhanced_setup_sync(struct hci_dev *hdev, void *data)
 	cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
 	cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
 
-	hci_dev_lock(hdev);
-
 	switch (conn->codec.id) {
 	case BT_CODEC_MSBC:
 		if (!find_next_esco_param(conn, esco_param_msbc,
@@ -625,6 +639,12 @@ void hci_sco_setup(struct hci_conn *conn, __u8 status)
 	if (!link || !link->conn)
 		return;
 
+	/* The link may already be up: a setup abandoned while pending can
+	 * complete after a new connection was made and be matched to it.
+	 */
+	if (!HCI_CONN_HANDLE_UNSET(link->conn->handle))
+		return;
+
 	BT_DBG("hcon %p", conn);
 
 	if (!status) {
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v3 3/6] Bluetooth: hci_event: Disconnect links that complete while being aborted
  2026-10-08 22:26 [PATCH v3 0/6] Bluetooth: Fix SCO setup failures after an abandoned setup Hitalo Souza
  2026-10-08 22:26 ` [PATCH v3 1/6] Bluetooth: hci_event: Don't fail a connected SCO link on setup errors Hitalo Souza
  2026-10-08 22:26 ` [PATCH v3 2/6] Bluetooth: hci_conn: Don't set up a SCO link that is already up Hitalo Souza
@ 2026-10-08 22:26 ` Hitalo Souza
  2026-10-08 22:26 ` [PATCH v3 4/6] Bluetooth: Don't leave abandoned SCO links up in the controller Hitalo Souza
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Hitalo Souza @ 2026-10-08 22:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, luiz.dentz, linux-kernel, Hitalo Souza

Since commit 16e3b6429159 ("Bluetooth: hci_conn: Fix modifying handle
while aborting"), and for LE since commit 181a42edddf5 ("Bluetooth: Make
handle of hci_conn be unique"), a connection that is being aborted
refuses the handle of its link when the link completes before the
connection is deleted, e.g. while the abort waits for its cancel
command. The link is up in the controller, though, and nothing
disconnects it: the event handler fails the connection or leaves it to
the abort, and the abort cancels the connect attempt and finds no handle
to disconnect. The handle then stays in use in the controller, e.g. a
SCO link left this way makes the controller reject every later setup
for the device until the ACL drops.

Disconnect the link when its connection refuses the handle, on
Connection Complete, Synchronous Connection Complete and LE (Enhanced)
Connection Complete, with the reason the connection was aborted for.
This is not done in hci_conn_set_handle() itself, as its other callers
set the handles of links that are not up yet.

Fixes: 16e3b6429159 ("Bluetooth: hci_conn: Fix modifying handle while aborting")
Fixes: 181a42edddf5 ("Bluetooth: Make handle of hci_conn be unique")
Assisted-by: LLM
Signed-off-by: Hitalo Souza <enghitalo@gmail.com>
---
 net/bluetooth/hci_event.c | 41 ++++++++++++++++++++++++++++++++++++---
 1 file changed, 38 insertions(+), 3 deletions(-)

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index cbe53e19e..1f9b47389 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3217,6 +3217,39 @@ static int hci_read_enc_key_size(struct hci_dev *hdev, struct hci_conn *conn)
 	return hci_send_cmd(hdev, HCI_OP_READ_ENC_KEY_SIZE, sizeof(cp), &cp);
 }
 
+/* Disconnects a link that came up in the controller but that no connection
+ * takes: nothing else would, and its handle would stay in use there.
+ */
+static void hci_disconnect_unused(struct hci_dev *hdev, u16 handle, u8 reason)
+{
+	struct hci_cp_disconnect cp;
+
+	/* Never for an invalid handle or one that a connection uses */
+	if (handle > HCI_CONN_HANDLE_MAX ||
+	    hci_conn_hash_lookup_handle(hdev, handle))
+		return;
+
+	bt_dev_dbg(hdev, "handle 0x%4.4x reason 0x%2.2x", handle, reason);
+
+	cp.handle = cpu_to_le16(handle);
+	cp.reason = reason;
+	hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(cp), &cp);
+}
+
+/* Sets the handle of a connection whose link came up. A connection that is
+ * being aborted refuses it, so its link is disconnected: the abort only
+ * cancels the connect attempt, and finds no handle to disconnect.
+ */
+static u8 hci_conn_complete_set_handle(struct hci_conn *conn, u16 handle)
+{
+	u8 status = hci_conn_set_handle(conn, handle);
+
+	if (status && conn->abort_reason)
+		hci_disconnect_unused(conn->hdev, handle, conn->abort_reason);
+
+	return status;
+}
+
 static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
 				  struct sk_buff *skb)
 {
@@ -3292,7 +3325,8 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
 	}
 
 	if (!status) {
-		status = hci_conn_set_handle(conn, __le16_to_cpu(ev->handle));
+		status = hci_conn_complete_set_handle(conn,
+						      __le16_to_cpu(ev->handle));
 		if (status)
 			goto done;
 
@@ -5208,7 +5242,8 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev, void *data,
 
 	switch (status) {
 	case 0x00:
-		status = hci_conn_set_handle(conn, __le16_to_cpu(ev->handle));
+		status = hci_conn_complete_set_handle(conn,
+						      __le16_to_cpu(ev->handle));
 		if (status) {
 			conn->state = BT_CLOSED;
 			break;
@@ -5974,7 +6009,7 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
 	 * hci_conn_failed function which is triggered by the HCI
 	 * request completion callbacks used for connecting.
 	 */
-	if (status || hci_conn_set_handle(conn, handle))
+	if (status || hci_conn_complete_set_handle(conn, handle))
 		goto unlock;
 
 	/* Drop the connection if it has been aborted */
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v3 4/6] Bluetooth: Don't leave abandoned SCO links up in the controller
  2026-10-08 22:26 [PATCH v3 0/6] Bluetooth: Fix SCO setup failures after an abandoned setup Hitalo Souza
                   ` (2 preceding siblings ...)
  2026-10-08 22:26 ` [PATCH v3 3/6] Bluetooth: hci_event: Disconnect links that complete while being aborted Hitalo Souza
@ 2026-10-08 22:26 ` Hitalo Souza
  2026-10-08 22:26 ` [PATCH v3 5/6] Bluetooth: hci_event: Disconnect an ACL link that completes after its abort Hitalo Souza
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Hitalo Souza @ 2026-10-08 22:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, luiz.dentz, linux-kernel, Hitalo Souza

Since commit a13f316e90fd ("Bluetooth: hci_conn: Consolidate code for
aborting connections"), aborting a SCO/eSCO connection whose setup is
pending, e.g. because its socket was closed, sends Create Connection
Cancel and deletes the hci_conn. That command cannot cancel a
synchronous connection, controllers just fail it (ACL Connection Already
Exists or Unknown Connection Identifier), and the link may still
complete afterwards. Unless another connection to the device takes it
over, its completion event then finds no connection waiting for it and
is ignored, so the link stays up in the controller, which rejects every
later setup for the device until the ACL drops (with Unsupported LMP
Parameter Value on a MediaTek MT7921). The same happens to a second
link completing for a connection that is already up, e.g. its own setup
after it took over the abandoned one.

There is no command to cancel a pending SCO/eSCO setup, so don't send
Create Connection Cancel for one, and disconnect a SCO/eSCO link that
completes with no connection waiting for it, with Synchronous
Connection Complete or, from Add SCO Connection, Connection Complete.

A controller may also answer the setup of a SCO_LINK connection with an
eSCO link, although only SCO packet types are allowed for it. Such a
link was ignored as well, and stayed up after the connection timed
out. Let the connection take it, as an eSCO connection already takes a
SCO link.

Link: https://github.com/bluez/bluez/issues/2562
Fixes: a13f316e90fd ("Bluetooth: hci_conn: Consolidate code for aborting connections")
Assisted-by: LLM
Signed-off-by: Hitalo Souza <enghitalo@gmail.com>
---
 net/bluetooth/hci_event.c | 43 +++++++++++++++++++++++++++++++++------
 net/bluetooth/hci_sync.c  |  8 ++++++++
 2 files changed, 45 insertions(+), 6 deletions(-)

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 1f9b47389..c825a99db 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3306,8 +3306,12 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
 
 			conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK,
 						       &ev->bdaddr);
-			if (!conn)
+			if (!conn) {
+				hci_disconnect_unused(hdev,
+						      __le16_to_cpu(ev->handle),
+						      HCI_ERROR_REMOTE_USER_TERM);
 				goto unlock;
+			}
 
 			conn->type = SCO_LINK;
 		}
@@ -3320,6 +3324,16 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
 	 * whether the connection is already set up.
 	 */
 	if (!HCI_CONN_HANDLE_UNSET(conn->handle)) {
+		/* Another SCO link for a connection that is already up has
+		 * no connection waiting for it either.
+		 */
+		if (!status && ev->link_type == SCO_LINK &&
+		    __le16_to_cpu(ev->handle) != conn->handle) {
+			hci_disconnect_unused(hdev, __le16_to_cpu(ev->handle),
+					      HCI_ERROR_REMOTE_USER_TERM);
+			goto unlock;
+		}
+
 		bt_dev_err(hdev, "Ignoring HCI_Connection_Complete for existing connection");
 		goto unlock;
 	}
@@ -5212,9 +5226,6 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev, void *data,
 
 	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
 	if (!conn) {
-		if (ev->link_type == ESCO_LINK)
-			goto unlock;
-
 		/* When the link type in the event indicates SCO connection
 		 * and lookup of the connection object fails, then check
 		 * if an eSCO connection object exists.
@@ -5223,10 +5234,14 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev, void *data,
 		 * SCO or eSCO. The eSCO connection is preferred and tried
 		 * to be setup first and until successfully established,
 		 * the link type will be hinted as eSCO.
+		 *
+		 * The other way around, a controller may answer the setup of
+		 * a SCO connection with an eSCO link.
 		 */
-		conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
+		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type == SCO_LINK ?
+					       ESCO_LINK : SCO_LINK, &ev->bdaddr);
 		if (!conn)
-			goto unlock;
+			goto unused;
 	}
 
 	/* The HCI_Synchronous_Connection_Complete event is only sent once per connection.
@@ -5236,6 +5251,13 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev, void *data,
 	 * whether the connection is already set up.
 	 */
 	if (!HCI_CONN_HANDLE_UNSET(conn->handle)) {
+		/* Another link for a connection that is already up, e.g. its
+		 * own setup completing after it took over an abandoned one,
+		 * has no connection waiting for it either.
+		 */
+		if (__le16_to_cpu(ev->handle) != conn->handle)
+			goto unused;
+
 		bt_dev_err(hdev, "Ignoring HCI_Sync_Conn_Complete event for existing connection");
 		goto unlock;
 	}
@@ -5295,6 +5317,15 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev, void *data,
 	hci_connect_cfm(conn, status);
 	if (status)
 		hci_conn_del(conn);
+	goto unlock;
+
+unused:
+	/* No connection waits for this link, e.g. because its setup was
+	 * abandoned while pending: don't leave it up in the controller.
+	 */
+	if (!status)
+		hci_disconnect_unused(hdev, __le16_to_cpu(ev->handle),
+				      HCI_ERROR_REMOTE_USER_TERM);
 
 unlock:
 	hci_dev_unlock(hdev);
diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
index 014ceaefd..7f5c96b72 100644
--- a/net/bluetooth/hci_sync.c
+++ b/net/bluetooth/hci_sync.c
@@ -5942,6 +5942,14 @@ static int hci_connect_cancel_sync(struct hci_dev *hdev, struct hci_conn *conn,
 		return 0;
 	}
 
+	if (conn->type == SCO_LINK || conn->type == ESCO_LINK) {
+		/* There is no command to cancel a pending SCO/eSCO setup. If
+		 * the link completes anyway, it is disconnected then, unless
+		 * a new connection to the device takes it.
+		 */
+		return 0;
+	}
+
 	if (hdev->hci_ver < BLUETOOTH_VER_1_2)
 		return 0;
 
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v3 5/6] Bluetooth: hci_event: Disconnect an ACL link that completes after its abort
  2026-10-08 22:26 [PATCH v3 0/6] Bluetooth: Fix SCO setup failures after an abandoned setup Hitalo Souza
                   ` (3 preceding siblings ...)
  2026-10-08 22:26 ` [PATCH v3 4/6] Bluetooth: Don't leave abandoned SCO links up in the controller Hitalo Souza
@ 2026-10-08 22:26 ` Hitalo Souza
  2026-10-08 22:26 ` [PATCH v3 6/6] Bluetooth: hci_event: Notify the driver only of SCO links that came up Hitalo Souza
  2026-10-09 13:57 ` [PATCH v3 0/6] Bluetooth: Fix SCO setup failures after an abandoned setup Luiz Augusto von Dentz
  6 siblings, 0 replies; 9+ messages in thread
From: Hitalo Souza @ 2026-10-08 22:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, luiz.dentz, linux-kernel, Hitalo Souza

Since commit a13f316e90fd ("Bluetooth: hci_conn: Consolidate code for
aborting connections"), aborting an ACL connection in BT_CONNECT sends
Create Connection Cancel and deletes the connection. For an incoming
connection that was accepted, e.g. one that MGMT_OP_DISCONNECT aborts
before it completes, the cancel fails at once as the device was never
paged, and the Connection Complete that follows finds no connection and
is ignored. The link then stays up in the controller with nothing to
disconnect it. The same happens with controllers older than 1.2, where
no cancel is sent at all.

Disconnect an ACL link that completes with no connection to take it,
unless an accept list entry makes it an auto-connection, which is
handled as before.

Fixes: a13f316e90fd ("Bluetooth: hci_conn: Consolidate code for aborting connections")
Assisted-by: LLM
Signed-off-by: Hitalo Souza <enghitalo@gmail.com>
---
 net/bluetooth/hci_event.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index c825a99db..14270711c 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3301,8 +3301,15 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
 				goto unlock;
 			}
 		} else {
-			if (ev->link_type != SCO_LINK)
+			if (ev->link_type != SCO_LINK) {
+				/* No connection takes this link, e.g. an
+				 * incoming one aborted after it was accepted
+				 */
+				hci_disconnect_unused(hdev,
+						      __le16_to_cpu(ev->handle),
+						      HCI_ERROR_REMOTE_USER_TERM);
 				goto unlock;
+			}
 
 			conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK,
 						       &ev->bdaddr);
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v3 6/6] Bluetooth: hci_event: Notify the driver only of SCO links that came up
  2026-10-08 22:26 [PATCH v3 0/6] Bluetooth: Fix SCO setup failures after an abandoned setup Hitalo Souza
                   ` (4 preceding siblings ...)
  2026-10-08 22:26 ` [PATCH v3 5/6] Bluetooth: hci_event: Disconnect an ACL link that completes after its abort Hitalo Souza
@ 2026-10-08 22:26 ` Hitalo Souza
  2026-10-09 13:57 ` [PATCH v3 0/6] Bluetooth: Fix SCO setup failures after an abandoned setup Luiz Augusto von Dentz
  6 siblings, 0 replies; 9+ messages in thread
From: Hitalo Souza @ 2026-10-08 22:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, luiz.dentz, linux-kernel, Hitalo Souza

hci_sync_conn_complete_evt() notifies the driver of the air mode of a
synchronous connection whether or not its link came up, while
hci_conn_complete_evt() only does it for a link that did. A connection
whose link failed, or that refused the handle as it is being aborted,
is deleted right after, which notifies HCI_NOTIFY_DISABLE_SCO. btusb
picks the alternate setting of its isochronous interface from the latest
of these notifications whenever the number of SCO connections changes,
and HCI_NOTIFY_DISABLE_SCO selects no air mode: with another SCO
connection still up, the interface ends up at alternate setting 0, which
stops the audio of the connection that is up.

Only notify the driver when the link came up.

Fixes: 1f8330ea1692 ("Bluetooth: add support to notify using SCO air mode")
Assisted-by: LLM
Signed-off-by: Hitalo Souza <enghitalo@gmail.com>
---
 net/bluetooth/hci_event.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 14270711c..28fefddf9 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -5307,10 +5307,11 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev, void *data,
 	}
 
 	bt_dev_dbg(hdev, "SCO connected with air mode: %02x", ev->air_mode);
-	/* Notify only in case of SCO over HCI transport data path which
-	 * is zero and non-zero value shall be non-HCI transport data path
+	/* Notify only of a link that came up, and only in case of SCO over
+	 * HCI transport data path which is zero and non-zero value shall be
+	 * non-HCI transport data path
 	 */
-	if (conn->codec.data_path == 0 && hdev->notify) {
+	if (!status && conn->codec.data_path == 0 && hdev->notify) {
 		switch (ev->air_mode) {
 		case 0x02:
 			hdev->notify(hdev, HCI_NOTIFY_ENABLE_SCO_CVSD);
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* RE: Bluetooth: Fix SCO setup failures after an abandoned setup
  2026-10-08 22:26 ` [PATCH v3 1/6] Bluetooth: hci_event: Don't fail a connected SCO link on setup errors Hitalo Souza
@ 2026-10-09  1:11   ` bluez.test.bot
  0 siblings, 0 replies; 9+ messages in thread
From: bluez.test.bot @ 2026-10-09  1:11 UTC (permalink / raw)
  To: linux-bluetooth, enghitalo

[-- Attachment #1: Type: text/plain, Size: 3600 bytes --]

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/series/1181908/

---Test result---

Test Summary:
CheckPatch                    FAIL      4.68 seconds
VerifyFixes                   PASS      0.12 seconds
VerifySignedoff               PASS      0.13 seconds
GitLint                       FAIL      2.01 seconds
SubjectPrefix                 PASS      0.72 seconds
BuildKernel                   PASS      29.53 seconds
CheckAllWarning               PASS      33.73 seconds
CheckSparse                   WARNING   37.15 seconds
BuildKernel32                 PASS      29.38 seconds
CheckKernelLLVM               PASS      35.39 seconds
TestRunnerSetup               PASS      779.04 seconds
TestRunner_l2cap-tester       PASS      12.84 seconds
TestRunner_iso-tester         PASS      17.07 seconds
TestRunner_bnep-tester        PASS      3.11 seconds
TestRunner_mgmt-tester        PASS      61.19 seconds
TestRunner_rfcomm-tester      PASS      4.49 seconds
TestRunner_sco-tester         PASS      5.38 seconds
TestRunner_ioctl-tester       PASS      4.64 seconds
TestRunner_mesh-tester        PASS      5.51 seconds
TestRunner_smp-tester         PASS      4.36 seconds
TestRunner_userchan-tester    PASS      3.19 seconds
TestRunner_6lowpan-tester     PASS      4.41 seconds
IncrementalBuild              PASS      54.47 seconds

Details
##############################
Test: CheckPatch - FAIL
Desc: Run checkpatch.pl script
Output:
[v3,1/6] Bluetooth: hci_event: Don't fail a connected SCO link on setup errors
ERROR: Please use git commit description style 'commit <12+ chars of sha1> ("<title line>")' - ie: 'commit a13f316e90fd ("Bluetooth: hci_conn: Consolidate code for aborting connections")'
#111: 
A link that is up can be the first one on the ACL since commit

total: 1 errors, 0 warnings, 0 checks, 44 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/home/runner/work/bluetooth-next/bluetooth-next/src/patch/14875449.patch has style problems, please review.

NOTE: Ignored message types: UNKNOWN_COMMIT_ID

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


##############################
Test: GitLint - FAIL
Desc: Run gitlint
Output:
[v3,3/6] Bluetooth: hci_event: Disconnect links that complete while being aborted

1: T1 Title exceeds max length (81>80): "[v3,3/6] Bluetooth: hci_event: Disconnect links that complete while being aborted"
[v3,5/6] Bluetooth: hci_event: Disconnect an ACL link that completes after its abort

1: T1 Title exceeds max length (84>80): "[v3,5/6] Bluetooth: hci_event: Disconnect an ACL link that completes after its abort"
##############################
Test: CheckSparse - WARNING
Desc: Run sparse tool with linux kernel
Output:
net/bluetooth/hci_event.c: note: in included file (through include/net/bluetooth/hci_core.h):net/bluetooth/hci_event.c: note: in included file (through include/net/bluetooth/hci_core.h):net/bluetooth/hci_event.c: note: in included file (through include/net/bluetooth/hci_core.h):net/bluetooth/hci_event.c: note: in included file (through include/net/bluetooth/hci_core.h):net/bluetooth/hci_event.c: note: in included file (through include/net/bluetooth/hci_core.h):


https://github.com/bluez/bluetooth-next/pull/891

---
Regards,
Linux Bluetooth


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v3 0/6] Bluetooth: Fix SCO setup failures after an abandoned setup
  2026-10-08 22:26 [PATCH v3 0/6] Bluetooth: Fix SCO setup failures after an abandoned setup Hitalo Souza
                   ` (5 preceding siblings ...)
  2026-10-08 22:26 ` [PATCH v3 6/6] Bluetooth: hci_event: Notify the driver only of SCO links that came up Hitalo Souza
@ 2026-10-09 13:57 ` Luiz Augusto von Dentz
  6 siblings, 0 replies; 9+ messages in thread
From: Luiz Augusto von Dentz @ 2026-10-09 13:57 UTC (permalink / raw)
  To: Hitalo Souza; +Cc: linux-bluetooth, marcel, linux-kernel

Hi Hitalo,

On Thu, Oct 8, 2026 at 6:26 PM Hitalo Souza <enghitalo@gmail.com> wrote:
>
> Since commit a13f316e90fd ("Bluetooth: hci_conn: Consolidate code for
> aborting connections"), closing a SCO socket while its setup is pending
> deletes the hci_conn, after a Create Connection Cancel that cannot
> cancel a synchronous connection. When a new socket connects right away,
> e.g. PipeWire recreating the HFP transport after a codec negotiation as
> in bluez/bluez#2562, the abandoned setup can still complete, and:
>
>  1. It is matched to the new connection by address, the controller then
>     rejects the new connection's own setup, and the rejection handler
>     fails the first link on the ACL, which is now the connected one,
>     without disconnecting it (patch 1).
>
>  2. It is matched to the new connection before that connection's own
>     setup was sent: Enhanced Setup Synchronous Connection goes through
>     the cmd_sync queue, and any setup waits for the ACL to leave sniff
>     mode. The setup is then sent anyway and rejected. This is the order
>     of events in the report (patch 2).
>
>  3. Nothing takes it over, or it is a second link for a connection
>     that is already up: the link stays up in the controller with no
>     connection for it, and the controller rejects every further setup
>     for the device until the ACL drops (patch 4).
>
> Patches 3 and 5 make links that complete for an aborted connection be
> disconnected in general, as Luiz suggested, not only SCO ones. Patch 3:
> a link (ACL, SCO/eSCO or LE) that completes while its connection is
> being aborted, which then refuses the handle since 16e3b6429159
> ("Bluetooth: hci_conn: Fix modifying handle while aborting") and, for
> LE, 181a42edddf5 ("Bluetooth: Make handle of hci_conn be unique").
> Patch 5: an incoming ACL connection aborted after it was accepted,
> which is deleted before its link completes. Patch 6 stops notifying
> the driver of the air mode of a SCO link that did not come up: with
> btusb, that notification and the one for the connection's deletion
> right after could stop the audio of another SCO connection. btusb can
> still do that when a SCO link that was up goes down while another one
> stays up; that is not changed here.
>
> In 1 and 2 the new connection keeps the link of the abandoned setup,
> with the parameters of that setup: the completion event does not say
> which setup it belongs to. Its Air_Mode would show a change between
> CVSD and transparent data, but the series does not act on it. An
> abandoned setup that fails after a new connection was made, in Command
> Status or in its completion event, is likewise applied to that
> connection. Before a13f316e90fd both happened in another way, as the
> next socket reused the pending hci_conn.
>
> If a controller answers the setup of a SCO_LINK connection (only SCO
> packet types allowed, e.g. with the disable_esco parameter of sco.c)
> with an eSCO link, that link was ignored, so the connect timed out and
> the link stayed up. Patch 4 now lets the connection take it, as an
> eSCO connection already takes a SCO link.
>
> Changes in v3:
> - Patch 4: a SCO_LINK connection takes an eSCO link that answers its
>   setup, instead of the link being ignored and left up (Sashiko). T6
>   now checks that the connection gets the link.
> - Patch 1: the commit message notes that a Command Status does not
>   tell which setup failed, which the patch does not change (Sashiko).
> - Rebased on bluetooth-next 97a128698d9d, without conflicts.
> - Tests for BlueZ's sco-tester and l2cap-tester that abort a connection
>   while its connection complete event is pending, as Luiz asked:
>   https://lore.kernel.org/linux-bluetooth/20261008215756.2710812-1-enghitalo@gmail.com/
> - v2: https://lore.kernel.org/linux-bluetooth/20261008151238.2138665-1-enghitalo@gmail.com/
>
> Changes in v2:
> - New patch 3, following Luiz's review: disconnect any link that
>   completes while its connection is being aborted, on Connection
>   Complete, Synchronous Connection Complete and LE Connection Complete.
>   It replaces the SCO-only handling of that case in v1's patch 3, and
>   covers the ACL and LE cases Sashiko pointed out.
> - Patch 4 (v1's patch 3) uses the helper of patch 3, and also
>   disconnects a second SCO link that completes with Connection Complete
>   for a connection that is already up (Sashiko).
> - New patch 5: disconnect an ACL link that completes after its
>   connection was aborted and deleted (an incoming connection).
> - New patch 6: notify the driver of the air mode only of a SCO link
>   that came up (Sashiko).
> - The disable_esco case is described as what it is: a controller
>   answering a SCO-only setup with an eSCO link.
> - New tests T5b, T7, T8 and T9.
> - v1: https://lore.kernel.org/linux-bluetooth/20261007154353.148223-1-enghitalo@gmail.com/
>
> Patch 2 relies on hci_enhanced_setup_sync() taking hdev->lock, since
> 024e05f73a4c ("Bluetooth: hci_conn: Lock parent access during enhanced
> SCO setup"); a backport to a kernel without that commit needs the lock
> taken around the new checks.
>
> Testing:
>
> - QEMU/KVM, bluetooth-next at 97a128698d9d and with each patch applied
>   in turn, x86_64 defconfig + kvm_guest.config + BT=y, BT_HCIVHCI=y. A
>   userspace program emulates the controller and the headset over
>   hci_vhci; the controller allows one eSCO link per ACL and rejects
>   further setups with 0x0a (0x12 in T1, as in the report), except in
>   T5, where it allows a second one. Each case was run over Setup
>   Synchronous Connection (L), Enhanced Setup Synchronous Connection (E)
>   and Add SCO Connection (A, controller without eSCO):
>
>   T0  connect, receive SCO data, close
>   T1  close a socket with its setup pending, connect a new one; the
>       first setup completes, then the new one is rejected
>   T1b like T1, but the first setup completes before the new one is
>       sent, which waits for the ACL to leave sniff mode
>   T1c like T1b, but the new setup waits in the cmd_sync queue (E only)
>   T2  close a socket with its setup pending, the setup completes
>       afterwards, connect a new socket (cancel answered 0x0b and 0x02)
>   T2b like T2, but the setup completes while the abort still waits in
>       the cmd_sync queue
>   T3  a setup rejected with 0x0d in Command Status
>   T4  like T2, but the abandoned setup completes with 0x22
>   T5  like T1, but the new setup completes too, with a second link
>   T5b an incoming SCO connection is up, and a second SCO link to the
>       device completes with Connection Complete (A only)
>   T6  disable_esco set, and the emulated controller answers the
>       SCO-only setup with an eSCO link (L and E): the connection gets
>       the link, receives SCO data and disconnects it when closed
>   T7  an ACL connect to another device is aborted while paging, and
>       the page succeeds as Create Connection Cancel arrives (cancel
>       answered 0x0b)
>   T8  with an emulated LE-only controller: an L2CAP LE connect is
>       aborted while LE Create Connection is pending, and the connection
>       completes as LE Create Connection Cancel arrives (cancel answered
>       0x0c); also with the cancel succeeding in time, where nothing may
>       be disconnected
>   T9  an incoming ACL connection is aborted with MGMT_OP_DISCONNECT
>       after it was accepted; Create Connection Cancel fails with 0x02,
>       then the link completes
>
>   In T1c the cmd_sync queue waits for a Read RSSI (from mgmt Get
>   Connection Information) that the emulator leaves unanswered; in T2b
>   it waits for an ACL connection to another device, whose Connection
>   Complete the emulator holds as during a page.
>
>                   T1   T1b  T1c  T2   T2b  T5   T5b  T6   T7   T8   T9
>   bluetooth-next  FAIL FAIL FAIL FAIL FAIL FAIL FAIL FAIL FAIL FAIL FAIL
>   + patch 1       pass FAIL FAIL FAIL FAIL FAIL FAIL FAIL FAIL FAIL FAIL
>   + patches 1-2   pass (*)  pass FAIL FAIL FAIL FAIL FAIL FAIL FAIL FAIL
>   + patches 1-3   pass (*)  pass FAIL pass FAIL FAIL FAIL pass pass FAIL
>   + patches 1-4   pass pass pass pass pass pass pass pass pass pass FAIL
>   + patches 1-5   pass pass pass pass pass pass pass pass pass pass pass
>   + patches 1-6   pass pass pass pass pass pass pass pass pass pass pass
>
>   T0, T3, T4 and the LE connect cancelled in time pass on every row.
>
>   The results are the same on L, E and A, except (*): pass on L and E,
>   FAIL on A, where the abandoned link is not taken over by a connection
>   that has not started its setup, and stays up until patch 4.
>
>   Without the series, the new socket gets EINVAL in T1 (the emulator
>   rejects with 0x12) and EMLINK in T1b and T1c (its duplicate setup is
>   rejected with 0x0a), the next connect gets EMLINK in T2 and T2b, and
>   the second links in T5 and T5b and the ACL and LE links in T7, T8 and
>   T9 are not disconnected (they stay up until the ACL drops, or for
>   good); in T6 the connect times out and the link stays up. With it,
>   the new sockets and the connection in T6 receive SCO data and no
>   Create Connection Cancel is sent for SCO; the links that nothing
>   takes over (T1b on A, T2, T2b, T7, T8, T9) and the second links in T5
>   and T5b are disconnected as soon as they complete, and T4 and the LE
>   connect cancelled in time send no Disconnect. No kernel warnings.
>   Patch 6 is not covered here, as hci_vhci has no notify callback.
>
> - BlueZ testers (master 866b0b8 with the new tests) in the same VM, on
>   the debug kernel below plus CRYPTO_USER_API_{HASH,SKCIPHER}, run
>   twice: with the series sco-tester (31), l2cap-tester (113) and
>   iso-tester (141) pass, and without it only the three new tests fail.
>   mgmt-tester has 8 to 10 LL Privacy failures of 506 per run, with and
>   without the series.
>
> - Real hardware, with v2 (v3 only changes what happens when a SCO_LINK
>   connection gets an eSCO link, which does not occur there): a MediaTek
>   MT7921 (USB 04ca:3802, legacy Setup Synchronous Connection because of
>   HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN) with a Sony WF-1000XM6, on
>   v7.1.13 with the series built as the bluetooth module (patch 2 needs
>   one change there, as hci_enhanced_setup_sync() does not take
>   hdev->lock in that version; the other functions touched are the same
>   as in bluetooth-next). With PipeWire 1.6.8 the abandoned setups were
>   first seen there: Create Connection Cancel was answered with Unknown
>   Connection Identifier, and the setup still completed afterwards.
>
>   A SCO socket was closed 150 ms into its setup and a new one connected
>   0.3 s or 2.5 s later, five times; each abandoned setup completed about
>   0.2 s after it started, before the new connect. Without the series the
>   first abandoned link after each ACL connect (two in the run) was left
>   up, and from then on the controller rejected every setup, plain
>   connects included, with Unsupported LMP Parameter Value (0x20) until
>   the ACL was dropped. With the series no Create Connection Cancel was
>   sent, each abandoned link was disconnected as soon as it completed,
>   and every new socket and the plain connects after them received SCO
>   data. An abandoned setup that failed (the headset rejects CVSD with
>   0x20) caused no Disconnect. Between the groups PipeWire switched the
>   headset from A2DP to HFP (mSBC) for a recording while I counted
>   aloud: speech was recorded all three times, with and without the
>   series. The cases of patches 1 and 2 did not occur there.
>
> - W=1 builds of net/bluetooth/ and drivers/bluetooth/, no warnings:
>   GCC 16.2.1 x86_64 allmodconfig and i386 defconfig, LLVM 22.1.8 arm64
>   defconfig, arm multi_v7_defconfig, riscv defconfig and powerpc
>   ppc64_defconfig (big-endian), with BT, BT_HCIBTUSB{,_MTK,_QCOM} and
>   BT_VIRTIO.
>
> - sparse v0.6.5-rc1 on the same directories: the same 16 reports with
>   and without the series, none on the lines touched here.
>
> - With the series, the same tests on a kernel with PROVE_LOCKING,
>   PROVE_RCU, KASAN, DEBUG_ATOMIC_SLEEP, DEBUG_LIST and
>   DEBUG_OBJECTS{,_WORK,_TIMERS} enabled: all pass on the three paths
>   and with the LE-only controller, with no lockdep, KASAN or
>   debugobjects reports, also while the BlueZ testers ran.
>
> The patches, the commit messages, this letter and the test programs
> were prepared with an AI assistant (see the Assisted-by tags), which
> reproduced the report in the emulator and wrote and tested the fixes;
> the real-hardware runs were done on my laptop with my headset.
>
> Hitalo Souza (6):
>   Bluetooth: hci_event: Don't fail a connected SCO link on setup errors
>   Bluetooth: hci_conn: Don't set up a SCO link that is already up
>   Bluetooth: hci_event: Disconnect links that complete while being
>     aborted
>   Bluetooth: Don't leave abandoned SCO links up in the controller
>   Bluetooth: hci_event: Disconnect an ACL link that completes after its
>     abort
>   Bluetooth: hci_event: Notify the driver only of SCO links that came up
>
>  net/bluetooth/hci_conn.c  |  24 +++++++-
>  net/bluetooth/hci_event.c | 124 ++++++++++++++++++++++++++++++++------
>  net/bluetooth/hci_sync.c  |   8 +++
>  3 files changed, 135 insertions(+), 21 deletions(-)
>
>
> base-commit: 97a128698d9dcacb9a15cdc5080718a644b12637
> --
> 2.55.0

Sashiko is flagging a few more problems:

https://sashiko.dev/#/patchset/20261008222616.2780570-1-enghitalo%40gmail.com

-- 
Luiz Augusto von Dentz

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2026-10-09 13:57 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-08 22:26 [PATCH v3 0/6] Bluetooth: Fix SCO setup failures after an abandoned setup Hitalo Souza
2026-10-08 22:26 ` [PATCH v3 1/6] Bluetooth: hci_event: Don't fail a connected SCO link on setup errors Hitalo Souza
2026-10-09  1:11   ` Bluetooth: Fix SCO setup failures after an abandoned setup bluez.test.bot
2026-10-08 22:26 ` [PATCH v3 2/6] Bluetooth: hci_conn: Don't set up a SCO link that is already up Hitalo Souza
2026-10-08 22:26 ` [PATCH v3 3/6] Bluetooth: hci_event: Disconnect links that complete while being aborted Hitalo Souza
2026-10-08 22:26 ` [PATCH v3 4/6] Bluetooth: Don't leave abandoned SCO links up in the controller Hitalo Souza
2026-10-08 22:26 ` [PATCH v3 5/6] Bluetooth: hci_event: Disconnect an ACL link that completes after its abort Hitalo Souza
2026-10-08 22:26 ` [PATCH v3 6/6] Bluetooth: hci_event: Notify the driver only of SCO links that came up Hitalo Souza
2026-10-09 13:57 ` [PATCH v3 0/6] Bluetooth: Fix SCO setup failures after an abandoned setup Luiz Augusto von Dentz

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.