Skip to content

Jaguar USB RX: 16 KB URBs + matching agg caps — restore the MediaTek host fix#317

Merged
josephnef merged 1 commit into
masterfrom
rx-16k-mtk
Jul 20, 2026
Merged

Jaguar USB RX: 16 KB URBs + matching agg caps — restore the MediaTek host fix#317
josephnef merged 1 commit into
masterfrom
rx-16k-mtk

Conversation

@josephnef

Copy link
Copy Markdown
Collaborator

Closes #314.

What

Restores the host-side half of @floppyhammer's MediaTek no-video fix (#19), lost when the RX path moved to the async URB ring and the #213 transport split deleted RtlUsbAdapter.cpp:

  • Jaguar1/2/3 RX rings: 16 KB URBs (was 32 KB), via new DeviceConfig::Rx::urb_bytes (env DEVOURER_RX_URB_BYTES, clamped ≥ 4096).
  • Jaguar2/3 halmac agg page-threshold 0x050x03 (20 KB → ≤12 KB): an aggregate must never span two URBs or the next_offset walk breaks. Deliberate divergence from the kernel's value, documented at both sites.
  • Kestrel untouched: the 8852C RXAGG LEN_TH (~20 KB) requires its 32 KB ring; the knob is documented 11ac-only.
  • Docs: CLAUDE.md hardware gotcha + docs/performance-tuning.md lever entry.

Why it's free on healthy hosts

The device-side aggregation caps (Jaguar1 rxagg_usb_size 0x3/0x1 — the surviving half of #19) mean every aggregate is ≤16 KB and ends its URB via short packet: a 32 KB URB never filled past 16 KB. The URB size change costs nothing; it only removes the shape MediaTek hosts can't complete.

The regression chain

  1. PixelPilot#6 (Sept 2024): no video on MTK devices; libusb_bulk_transferLIBUSB_ERROR_TIMEOUT forever (diagnosis by @floppyhammer, Jan 2025).
  2. Fix libusb_bulk_transfer timeout on some Android devices #19 (bbc7385, Mar 2026): 16 KB reads + ≤16 KB aggregation. Validated on-device by two reporters. PixelPilot#97 pins it.
  3. Concurrent TX+RX on one adapter: StartRxLoop splits bring-up from the RX loop #158/Jaguar1 RX: unify onto the async URB queue — fixes the radxa sounding TX wedge #164/RX URBs: infinite timeout — stop the darwin idle-RX timeout flood #168 async ring + PCIe transport (vfio-pci) — RTL8821CE, RX + TX end-to-end #213 split (40e3a2a): aggregation half survives, host reads regress to 32 KB.
  4. PixelPilot#104 (Jul 13): first Android build of the async ring. Jul 19: no-video reports return on the same devices.

Validation

  • ctest 36/36 green (Linux, system toolchain)
  • Desktop bench: tests/regress.py matrices + delivery A/B 32K-vs-16K URBs — parity on J1/J2/J3 (table below)
  • On-device MTK: PixelPilot test APK to the Remove color code in logger #6 volunteers (Dimensity 810 + MT6765), plus one Snapdragon no-regression check

🤖 Generated with Claude Code

Bench results (2026-07-20, local rig)

Delivery A/B, devourer-RX cells, 15 s flood cells (tests/regress.py, DEVOURER_RX_URB_BYTES control arm):

RX chip (gen) TX ch 16 KB URBs 32 KB URBs 16 KB repeat
RTL8812AU (J1) 8821AU devourer flood 6 7400/8000 7400/8000 7200/8000
RTL8812AU (J1) 8821AU kernel 6 300/327 300/333 300/324
RTL8812BU (J2, agg 0x03) 8812AU devourer flood 36 8400/8500 8400/8500
RTL8812EU (J3, agg 0x03) 8812AU devourer flood 36 8200/8500 8200/8500
RTL8812EU (J3, agg 0x03) 8812AU kernel 36 300/315 300/320

Drift between arms matches the kernel-RX control cells (7217→7401→7355) — the URB size is invisible on healthy hosts, as predicted: with ≤16 KB aggregates each aggregate ends its URB via short packet, so a 32 KB buffer never filled past 16 KB. The J2/J3 agg 0x05→0x03 change shows no delivery cost (98.8% / 96.5% flood delivery, in line with this rig's history). Full 2×2 kernel-driver matrices pass on J1/J2 (ch 6 + ch 36); the J3 kernel cells are structurally absent (no kernel driver for the EU on this host). No 8814AU on the rig today — its delta is nil by construction (DMA-agg is 2 KB, far under either URB size; the multi-URB pool is untouched).

@josephnef josephnef mentioned this pull request Jul 20, 2026
…host fix (#314)

Some MediaTek Android xhci/usbfs stacks (Dimensity 810, Helio G99, MT6765)
never complete a bulk-IN read larger than 16 KB — LIBUSB_ERROR_TIMEOUT
forever, zero RX with a green init (OpenIPC/PixelPilot#6). floppyhammer's
#19 fixed this with 16 KB host reads plus ≤16 KB device-side RX aggregation;
the async-ring rewrites (#158/#164/#168) and the #213 transport split
(40e3a2a) kept the aggregation half but regressed the host reads to 32 KB
URBs on every 11ac generation. PixelPilot#104 shipped the first Android
build of the async ring and the no-video reports came straight back.

- Jaguar1/2/3 RX rings: 16 KB URBs (DeviceConfig::Rx::urb_bytes, env
  DEVOURER_RX_URB_BYTES, clamped >= 4096). Free on healthy hosts: with
  aggregates capped ≤16 KB a 32 KB URB never filled past 16 KB anyway —
  each aggregate ends its URB via short packet.
- Jaguar2/3 halmac agg page-threshold 0x05 (20 KB) -> 0x03 (≤12 KB): an
  aggregate must never span two URBs or the next_offset walk breaks.
  Deliberate divergence from the kernel's 0x05, documented at both sites.
- Kestrel untouched: the 8852C RXAGG LEN_TH (~20 KB) requires its 32 KB
  ring; the knob is documented as 11ac-only.
- Docs: CLAUDE.md hardware gotcha + performance-tuning.md lever entry.

ctest 36/36. Desktop bench (regress 2x2, goodput A/B) and on-device MTK
validation via PixelPilot#6 volunteers tracked in #314.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@josephnef
josephnef merged commit b7c50ec into master Jul 20, 2026
18 checks passed
@josephnef
josephnef deleted the rx-16k-mtk branch July 20, 2026 11:00
josephnef added a commit to OpenIPC/PixelPilot that referenced this pull request Jul 20, 2026
…RX ring

Fixes the #6 regression reported on 2026-07-19. PR #104 bumped devourer
past the transport split that deleted RtlUsbAdapter.cpp: the device-side
half of floppyhammer's fix (16 KB RX aggregation caps) survived, but the
host side regressed from 16 KB reads to 32 KB URBs — the exact transfer
shape some MediaTek xhci/usbfs stacks (Dimensity 810, Helio G99, MT6765)
never complete: LIBUSB_ERROR_TIMEOUT forever, zero RX, no video.

- devourer submodule -> b7c50ec (OpenIPC/devourer#317, merged master):
  16 KB URBs on all 11ac generations + matching Jaguar2/3 aggregation
  caps, tracked in OpenIPC/devourer#314. Bench-validated at delivery
  parity on RTL8812AU / RTL8812BU / RTL8812EU.
- WfbngLink.cpp: cfg.usb.rx_zerocopy = false — keep the RX ring on plain
  heap buffers; the dev-mem zerocopy path is unvalidated on Android vendor
  kernels and every previously working Android build shipped the heap path.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Jaguar USB RX: 32 KB URBs regress MediaTek Android hosts (PixelPilot no-video) — restore the ≤16 KB read shape lost in the #213 transport split

1 participant