Re: [PATCH v4 1/1] Bluetooth: btusb: support larger LE packets on TP-Link UB500
From: Luiz Augusto von Dentz
Date: Thu Oct 29 2026 - 13:52:25 EST
Hi Kyle,
On Thu, Oct 29, 2026 at 1:47 PM Kyle Pepper <cochcoder@xxxxxxxxx> wrote:
>
> The TP-Link UB500 (2357:0604) with RTL8761BU firmware 0xdfc6d922
> reports an LE HCI packet length of 27 bytes and eight packets. It
> separately reports a maximum Link Layer TX data length of 251 bytes.
> Direct HCI user-channel transfers verified intact reception and
> completion of sixteen 251-byte packets, with one outstanding at a time.
>
> Use 251-byte LE HCI packets automatically on this device when its
> reported values match. Limit both the initial LE credits and their
> refill ceiling to one, matching the verified number of outstanding
> enlarged packets. Leave BR/EDR buffer fields unchanged.
>
> Skip the override when the reported values differ instead of failing
> controller initialization. A different firmware revision can continue
> using its reported HCI buffers.
>
> Assisted-by: LLM
> Signed-off-by: Kyle Pepper <cochcoder@xxxxxxxxx>
> ---
> v4:
> - Skip mismatched buffer reports without failing controller bring-up.
> - Limit enlarged LE packets to one initial and refill credit.
> - Submit as PATCH v4 and shorten the source wording.
>
> The first two changes address Sashiko review 219856:
> https://sashiko.dev/#/patchset/20261029023235.1280321-1-cochcoder%40proton.me
>
> Validation: baseline and revised btusb_main.o compile with W=1; strict
> checkpatch and compiled callback regression controls pass. The earlier
> raw-radio capture verifies 48 intact payloads and completions: sixteen
> each at 27, 167 and 251 bytes, with one outstanding packet at a time.
>
> The Link Layer maximum is not a measurement of HCI storage capacity.
> The revised callback has not been exercised on hardware. Sustained audio,
> mixed BR/EDR traffic, other firmware and exceptional congestion remain
> unverified. The override applies automatically only to the matching UB500
> device and the observed buffer reports.
>
> drivers/bluetooth/btusb_main.c | 18 ++++++++++++++++++
> 1 file changed, 18 insertions(+)
>
> diff --git a/drivers/bluetooth/btusb_main.c b/drivers/bluetooth/btusb_main.c
> index 92a78a7e6..b32d3acc6 100644
> --- a/drivers/bluetooth/btusb_main.c
> +++ b/drivers/bluetooth/btusb_main.c
> @@ -2972,6 +2972,21 @@ static int btusb_setup_realtek(struct hci_dev *hdev)
> return ret;
> }
>
> +static int btusb_ub500_post_init(struct hci_dev *hdev)
> +{
> + if (hdev->le_mtu != 27 ||
> + hdev->le_pkts != 8 || hdev->le_cnt != 8 ||
> + hdev->le_max_tx_len != 251)
> + return 0;
> +
> + bt_dev_info(hdev, "LE ACL MTU 27 -> %u; LE packets 8 -> 1",
> + hdev->le_max_tx_len);
> + hdev->le_mtu = hdev->le_max_tx_len;
> + hdev->le_pkts = 1;
> + hdev->le_cnt = 1;
Setting this to 1 would make transfers awfully long, as you would only
be able to send one packet at a time.
> + return 0;
> +}
> +
> static int btusb_recv_event_realtek(struct hci_dev *hdev, struct sk_buff *skb)
> {
> if (skb->len >= HCI_EVENT_HDR_SIZE + 1 &&
> @@ -4715,6 +4730,9 @@ static int btusb_probe(struct usb_interface *intf,
> (id->driver_info & BTUSB_REALTEK)) {
> btrtl_set_driver_name(hdev, btusb_driver.name);
> hdev->setup = btusb_setup_realtek;
> + if (le16_to_cpu(data->udev->descriptor.idVendor) == 0x2357 &&
> + le16_to_cpu(data->udev->descriptor.idProduct) == 0x0604)
> + hdev->post_init = btusb_ub500_post_init;
> hdev->shutdown = btrtl_shutdown_realtek;
> hdev->reset = btusb_rtl_reset;
> hdev->hw_error = btusb_rtl_hw_error;
>
> base-commit: 1081a6ef8f1e0661fd52eb3f878691b0b96cdff9
> --
> 2.56.0
>
>
--
Luiz Augusto von Dentz