* [RFC PATCH] Bluetooth: hci_event: negotiate LE Data Length after features
@ 2026-10-13 3:35 Kyle Pepper
2026-10-13 4:24 ` [RFC] " bluez.test.bot
2026-10-13 14:30 ` [RFC PATCH] " Luiz Augusto von Dentz
0 siblings, 2 replies; 3+ messages in thread
From: Kyle Pepper @ 2026-10-13 3:35 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Marcel Holtmann, Luiz Augusto von Dentz, linux-kernel
Request the controller transmit limits once both peers support DLE.
Queue the connection with a reference so pending requests coalesce and
connection deletion cancels them. Check the connection under the device
lock before constructing the command.
Assisted-by: OpenCode:gpt-6.1-sol
Signed-off-by: Kyle Pepper <cochcoder@proton.me>
---
Submission review notes (not part of the commit message):
The user reports that retaining the explicit DLE request enables the N8
to disconnect automatically after audio stops, whereas removing it
leaves the device connected. This idle-transition behavior is the
reported reason for retaining the topic, not an in-stream timeout.
October 9 no-DLE trials already negotiate TX 251 octets / 2120 us and
stream successfully; startup throughput alone does not test idle behavior.
The supplied captures do not establish a controlled post-STOP comparison
or the causal mechanism. This patch requests data length during setup;
it does not itself implement STOP or issue a disconnect command.
The claimed ASHA idle-disconnect requirement needs a protocol citation.
The corrected ownership implementation is included in the working kernel.
Native disconnect/handle reuse, LL ordering and post-snapshot races remain
unproved. Submit as an independent RFC with these limitations disclosed.
include/net/bluetooth/hci_sync.h | 1 +
net/bluetooth/hci_event.c | 10 +++++++
net/bluetooth/hci_sync.c | 47 ++++++++++++++++++++++++++++++++
3 files changed, 58 insertions(+)
diff --git a/include/net/bluetooth/hci_sync.h b/include/net/bluetooth/hci_sync.h
index 59cb918d1..5a37d3e50 100644
--- a/include/net/bluetooth/hci_sync.h
+++ b/include/net/bluetooth/hci_sync.h
@@ -194,3 +194,4 @@ int hci_le_read_remote_features(struct hci_conn *conn);
int hci_acl_change_pkt_type(struct hci_conn *conn, u16 pkt_type);
int hci_le_set_phy(struct hci_conn *conn, u8 tx_phys, u8 rx_phys);
+int hci_le_set_data_len(struct hci_conn *conn);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index c055d16cf..4035f2659 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -6846,6 +6846,16 @@ static void hci_le_remote_feat_complete_evt(struct hci_dev *hdev, void *data,
conn->le_tx_def_phys &= ~HCI_LE_SET_PHY_CODED;
conn->le_rx_def_phys &= ~HCI_LE_SET_PHY_CODED;
}
+
+ /* Request the controller maximum when both sides support
+ * LL Data Length Extension. The Link Layer negotiates
+ * the remote limits (Core v5.4, Vol 6, Part B,
+ * Sec. 4.5.10).
+ */
+ if ((hdev->le_features[0] & HCI_LE_DATA_LEN_EXT) &&
+ (conn->le_features[0] & HCI_LE_DATA_LEN_EXT) &&
+ hdev->le_max_tx_len > 0x001b)
+ hci_le_set_data_len(conn);
}
if (conn->state == BT_CONFIG) {
diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
index efbd2e538..20c690007 100644
--- a/net/bluetooth/hci_sync.c
+++ b/net/bluetooth/hci_sync.c
@@ -8123,3 +8123,50 @@ int hci_le_set_phy(struct hci_conn *conn, u8 tx_phys, u8 rx_phys)
return (err == -EEXIST) ? 0 : err;
}
+
+static void le_set_data_len_complete(struct hci_dev *hdev, void *data,
+ int err)
+{
+ struct hci_conn *conn = data;
+
+ bt_dev_dbg(hdev, "err %d", err);
+
+ hci_conn_put(conn);
+}
+
+static int hci_le_set_data_len_sync(struct hci_dev *hdev, void *data)
+{
+ struct hci_conn *conn = data;
+ struct hci_cp_le_set_data_len cp;
+
+ hci_dev_lock(hdev);
+
+ if (!hci_conn_valid(hdev, conn) || conn->type != LE_LINK ||
+ (conn->state != BT_CONNECTED && conn->state != BT_CONFIG)) {
+ hci_dev_unlock(hdev);
+ return -ECANCELED;
+ }
+
+ cp.handle = cpu_to_le16(conn->handle);
+ cp.tx_len = cpu_to_le16(hdev->le_max_tx_len);
+ cp.tx_time = cpu_to_le16(hdev->le_max_tx_time);
+
+ hci_dev_unlock(hdev);
+
+ return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_DATA_LEN,
+ sizeof(cp), &cp, HCI_CMD_TIMEOUT);
+}
+
+int hci_le_set_data_len(struct hci_conn *conn)
+{
+ struct hci_dev *hdev = conn->hdev;
+ int err;
+
+ err = hci_cmd_sync_queue_once(hdev, hci_le_set_data_len_sync,
+ hci_conn_get(conn),
+ le_set_data_len_complete);
+ if (err)
+ hci_conn_put(conn);
+
+ return (err == -EEXIST) ? 0 : err;
+}
base-commit: 964430c038967fd06643e866f68115664e1a1bd1
^ permalink raw reply related [flat|nested] 3+ messages in thread* RE: [RFC] Bluetooth: hci_event: negotiate LE Data Length after features
2026-10-13 3:35 [RFC PATCH] Bluetooth: hci_event: negotiate LE Data Length after features Kyle Pepper
@ 2026-10-13 4:24 ` bluez.test.bot
2026-10-13 14:30 ` [RFC PATCH] " Luiz Augusto von Dentz
1 sibling, 0 replies; 3+ messages in thread
From: bluez.test.bot @ 2026-10-13 4:24 UTC (permalink / raw)
To: linux-bluetooth, cochcoder
[-- Attachment #1: Type: text/plain, Size: 1813 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/1184346/
---Test result---
Test Summary:
CheckPatch PASS 0.89 seconds
VerifyFixes PASS 0.08 seconds
VerifySignedoff PASS 0.08 seconds
GitLint PASS 0.23 seconds
SubjectPrefix PASS 0.07 seconds
BuildKernel PASS 22.62 seconds
CheckAllWarning PASS 26.01 seconds
CheckSparse WARNING 28.12 seconds
BuildKernel32 PASS 23.94 seconds
CheckKernelLLVM PASS 26.98 seconds
TestRunnerSetup PASS 528.87 seconds
TestRunner_l2cap-tester PASS 13.34 seconds
TestRunner_iso-tester PASS 9.71 seconds
TestRunner_bnep-tester PASS 2.84 seconds
TestRunner_mgmt-tester PASS 87.94 seconds
TestRunner_rfcomm-tester PASS 4.08 seconds
TestRunner_sco-tester PASS 5.06 seconds
TestRunner_ioctl-tester PASS 4.38 seconds
TestRunner_mesh-tester PASS 5.43 seconds
TestRunner_smp-tester PASS 3.96 seconds
TestRunner_userchan-tester PASS 2.82 seconds
TestRunner_6lowpan-tester PASS 3.97 seconds
IncrementalBuild PASS 21.61 seconds
Details
##############################
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):
https://github.com/bluez/bluetooth-next/pull/910
---
Regards,
Linux Bluetooth
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [RFC PATCH] Bluetooth: hci_event: negotiate LE Data Length after features
2026-10-13 3:35 [RFC PATCH] Bluetooth: hci_event: negotiate LE Data Length after features Kyle Pepper
2026-10-13 4:24 ` [RFC] " bluez.test.bot
@ 2026-10-13 14:30 ` Luiz Augusto von Dentz
1 sibling, 0 replies; 3+ messages in thread
From: Luiz Augusto von Dentz @ 2026-10-13 14:30 UTC (permalink / raw)
To: Kyle Pepper; +Cc: linux-bluetooth, Marcel Holtmann, linux-kernel
Hi Kyle,
On Mon, Oct 12, 2026 at 11:35 PM Kyle Pepper <cochcoder@proton.me> wrote:
>
> Request the controller transmit limits once both peers support DLE.
> Queue the connection with a reference so pending requests coalesce and
> connection deletion cancels them. Check the connection under the device
> lock before constructing the command.
>
> Assisted-by: OpenCode:gpt-6.1-sol
> Signed-off-by: Kyle Pepper <cochcoder@proton.me>
> ---
> Submission review notes (not part of the commit message):
> The user reports that retaining the explicit DLE request enables the N8
> to disconnect automatically after audio stops, whereas removing it
> leaves the device connected. This idle-transition behavior is the
> reported reason for retaining the topic, not an in-stream timeout.
> October 9 no-DLE trials already negotiate TX 251 octets / 2120 us and
> stream successfully; startup throughput alone does not test idle behavior.
> The supplied captures do not establish a controlled post-STOP comparison
> or the causal mechanism. This patch requests data length during setup;
> it does not itself implement STOP or issue a disconnect command.
> The claimed ASHA idle-disconnect requirement needs a protocol citation.
> The corrected ownership implementation is included in the working kernel.
> Native disconnect/handle reuse, LL ordering and post-snapshot races remain
> unproved. Submit as an independent RFC with these limitations disclosed.
>
> include/net/bluetooth/hci_sync.h | 1 +
> net/bluetooth/hci_event.c | 10 +++++++
> net/bluetooth/hci_sync.c | 47 ++++++++++++++++++++++++++++++++
> 3 files changed, 58 insertions(+)
>
> diff --git a/include/net/bluetooth/hci_sync.h b/include/net/bluetooth/hci_sync.h
> index 59cb918d1..5a37d3e50 100644
> --- a/include/net/bluetooth/hci_sync.h
> +++ b/include/net/bluetooth/hci_sync.h
> @@ -194,3 +194,4 @@ int hci_le_read_remote_features(struct hci_conn *conn);
>
> int hci_acl_change_pkt_type(struct hci_conn *conn, u16 pkt_type);
> int hci_le_set_phy(struct hci_conn *conn, u8 tx_phys, u8 rx_phys);
> +int hci_le_set_data_len(struct hci_conn *conn);
> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
> index c055d16cf..4035f2659 100644
> --- a/net/bluetooth/hci_event.c
> +++ b/net/bluetooth/hci_event.c
> @@ -6846,6 +6846,16 @@ static void hci_le_remote_feat_complete_evt(struct hci_dev *hdev, void *data,
> conn->le_tx_def_phys &= ~HCI_LE_SET_PHY_CODED;
> conn->le_rx_def_phys &= ~HCI_LE_SET_PHY_CODED;
> }
> +
> + /* Request the controller maximum when both sides support
> + * LL Data Length Extension. The Link Layer negotiates
> + * the remote limits (Core v5.4, Vol 6, Part B,
> + * Sec. 4.5.10).
> + */
> + if ((hdev->le_features[0] & HCI_LE_DATA_LEN_EXT) &&
> + (conn->le_features[0] & HCI_LE_DATA_LEN_EXT) &&
> + hdev->le_max_tx_len > 0x001b)
> + hci_le_set_data_len(conn);
We use HCI_OP_LE_WRITE_DEF_DATA_LEN to setup this for every
connection, so either the controller has a bug and doesn't trigger
trigger DLE or something else is off here. In case it is really a
specific controller then we might need a quirk which once set by the
driver indicates the host has to perform the DLE procedure manually
like above.
> }
>
> if (conn->state == BT_CONFIG) {
> diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
> index efbd2e538..20c690007 100644
> --- a/net/bluetooth/hci_sync.c
> +++ b/net/bluetooth/hci_sync.c
> @@ -8123,3 +8123,50 @@ int hci_le_set_phy(struct hci_conn *conn, u8 tx_phys, u8 rx_phys)
>
> return (err == -EEXIST) ? 0 : err;
> }
> +
> +static void le_set_data_len_complete(struct hci_dev *hdev, void *data,
> + int err)
> +{
> + struct hci_conn *conn = data;
> +
> + bt_dev_dbg(hdev, "err %d", err);
> +
> + hci_conn_put(conn);
> +}
> +
> +static int hci_le_set_data_len_sync(struct hci_dev *hdev, void *data)
> +{
> + struct hci_conn *conn = data;
> + struct hci_cp_le_set_data_len cp;
> +
> + hci_dev_lock(hdev);
> +
> + if (!hci_conn_valid(hdev, conn) || conn->type != LE_LINK ||
> + (conn->state != BT_CONNECTED && conn->state != BT_CONFIG)) {
> + hci_dev_unlock(hdev);
> + return -ECANCELED;
> + }
> +
> + cp.handle = cpu_to_le16(conn->handle);
> + cp.tx_len = cpu_to_le16(hdev->le_max_tx_len);
> + cp.tx_time = cpu_to_le16(hdev->le_max_tx_time);
> +
> + hci_dev_unlock(hdev);
> +
> + return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_DATA_LEN,
> + sizeof(cp), &cp, HCI_CMD_TIMEOUT);
> +}
> +
> +int hci_le_set_data_len(struct hci_conn *conn)
> +{
> + struct hci_dev *hdev = conn->hdev;
> + int err;
> +
> + err = hci_cmd_sync_queue_once(hdev, hci_le_set_data_len_sync,
> + hci_conn_get(conn),
> + le_set_data_len_complete);
> + if (err)
> + hci_conn_put(conn);
> +
> + return (err == -EEXIST) ? 0 : err;
> +}
>
> base-commit: 964430c038967fd06643e866f68115664e1a1bd1
>
--
Luiz Augusto von Dentz
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-10-13 14:30 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-13 3:35 [RFC PATCH] Bluetooth: hci_event: negotiate LE Data Length after features Kyle Pepper
2026-10-13 4:24 ` [RFC] " bluez.test.bot
2026-10-13 14:30 ` [RFC PATCH] " Luiz Augusto von Dentz
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox