RTL8814AU: TX FIFO bring-up fixes + cross-adapter validation tooling#24
Merged
Conversation
WiFiDriverTxDemo previously only supported the Termux/Android pattern of taking a USB fd as argv[1] and wrapping it via libusb_wrap_sys_ device. On a regular Linux libusb context that path doesn't apply, and the demo also forked an RX child to run alongside TX on the same USB handle — which races on a libusb context that isn't fork-safe and crashes both processes with "rtw_read: iostream error" before TX even begins. Changes: - txdemo: when argv[1] is absent or non-numeric, fall through to a VID/PID open against the same Realtek PID list as the RX demo (0x8812 / 0x0811 / 0xa811 / 0xb811 / 0x8813). The Termux fd path is preserved when argv[1] is a positive int. Adds DEVOURER_PID, DEVOURER_CHANNEL, DEVOURER_SKIP_RESET env vars (parity with RX demo). - txdemo: gate the fork-RX child behind DEVOURER_TX_WITH_RX=1. Default is TX-only on a single handle. Cross-adapter validation (TX on one adapter, RX on another) is the only configuration that actually works on plain Linux. - txdemo: throttle the TX loop with usleep(2000) and log every Nth TX so it doesn't peg a core or spam stdout. - demo (RX) + txdemo (RX-when-DEVOURER_TX_WITH_RX): detect the txdemo's hardcoded injected-beacon SA (57:42:75:05:d6:00) and log <devourer-tx-hit> on match. Provides a clean signal for cross- adapter TX validation — each hit is one frame round-tripped over the air. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The 8812-path HalModule init steps that program the TX FIFO silently no-op
on the 8814AU. Three separate chip-init bugs that have to be fixed before
any TX path can work on this chip:
1) **Page allocation.** _InitQueueReservedPage_8812AUsb and
_InitTxBufferBoundary_8812AUsb write 8-bit fields in REG_RQPN /
REG_RQPN_NPQ (0x200-0x202) and REG_BCNQ_BDNY / REG_MGQ_BDNY /
REG_TRXFF_BNDY (0x424-... 8-bit). That register set is the 8812's
~256-page TX FIFO model. The 8814 has a 2048-page TX FIFO and uses
completely different registers: 32-bit REG_FIFOPAGE_INFO_{1..5}_8814A
(0x230-0x240) for per-queue page counts, 16-bit REG_TXPKTBUF_BCNQ_BDNY
/BCNQ1_BDNY/MGQ_PGBNDY for queue boundaries, plus REG_FIFOPAGE_CTRL_2
for BCNQ head pages.
Port _InitQueueReservedPage_8814AUsb + _InitPageBoundary_8814AUsb from
upstream hal/rtl8814a/usb/usb_halinit.c. Dispatch on CHIP_8814A so the
8812 path stays untouched. Register addresses + page constants
extracted into a local `namespace rtl8814a` because the upstream
rtl8814a_spec.h / rtl8814a_hal.h pull in kernel-only deps
(drv_conf.h, hal_data.h) we can't satisfy in userspace.
2) **Auto-LLT trigger.** Without HW auto-LLT firing post-fwdl, the chip's
per-queue free-page linked-list never gets built — the page counts we
just wrote are advertised but no actual pages are linked into the
per-queue free lists. TX would have nowhere to land buffer headers
even if the rest of bring-up were correct.
Upstream's hal/rtl8814a/rtl8814a_hal_init.c::InitLLTTable8814A writes
BIT0 of an 8-bit read at 0x208 and polls BIT0 to clear. That is the
wrong bit — verified empirically: the trigger never fires and the
poll exits in 0 iterations because BIT0 was never set in the chip's
response. The generic BIT_AUTO_INIT_LLT in hal_com_reg.h:1424 says
BIT(16) of the 32-bit register at 0x208 (aliased REG_TDECTRL). Use a
32-bit RMW with the correct BIT(16) trigger.
Verified the fix lands: REG_AUTO_LLT readback shows BIT16 self-cleared
within 2ms after our trigger, confirming the chip processed it.
3) **REG_CR preserve.** Some 8812-path init helpers reset REG_CR back to
only MACTXEN|MACRXEN (0xC0). Our existing final-state force-write of
0x00FF restored the DMA + protocol + scheduler bits but clobbered any
high bits firmware may have set. Read REG_CR observed-value first,
then OR-in our minimum-required low byte. Defensive — verified that
on this hardware fw doesn't set any high bits, but it's the safer
shape.
Each of the three is necessary but not by itself sufficient for TX. TX
end-to-end validation is still WIP (tracked separately). RX path is
unaffected by all three changes.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…R_TX_EP Add three diagnostic hooks that make future 8814 TX investigations tractable without rebuilding. All gated behind CHIP_8814A or an opt-in env var; the 8812 path is untouched at runtime. - HalModule::rtl8812au_hal_init: dump the registers that gate USB→TX dataflow at the end of init (REG_CR, TXPAUSE, FWHW_TXQ_CTRL, FIFOPAGE_CTRL_2, MGQ_PGBNDY, FIFOPAGE_INFO_1/5, MCUFWDL, TXDMA_STATUS, TXDMA_OFFSET_CHK, HWSEQ_CTRL via both 8-bit and 32-bit byte-3 access, TCR, RCR). One log line per register — the Logger's homegrown format helper truncates lines with too many placeholders. - RtlUsbAdapter::send_packet: on the first call only, dump CR / TXPAUSE / TXDMA_OFFSET_CHK / FWHW_TXQ_CTRL / MCUFWDL / HCIPWR. Surfaces any clobber between init-end and the actual first TX (e.g. SetMonitorChannel writing registers). - RtlUsbAdapter::send_packet: DEVOURER_TX_EP=0xNN overrides the hardcoded bulk OUT endpoint 0x02. Lets bisecting EP routing without a rebuild (0x03 = NQ, 0x04 = LQ on the 8814's 3-OUT-EP layout). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
MSVC doesn't ship <unistd.h>/usleep so the Windows CI build fails with "identifier not found". Use std::this_thread::sleep_for which is portable and already pulled in by the existing <thread> include in this file. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three logically separate improvements that fell out of investigating the
RTL8814AU TX path. TX is still not validated end-to-end, but each change
in this PR is independently correct and verified on hardware to not regress
the existing RX path on either 8812 or 8814.
Commits
demo: cross-adapter TX-validation tooling for the Jaguar family
txdemolearns a Linux VID/PID open path (Termuxargv[1]=fdstill workswhen present and parses to a positive int).
DEVOURER_TX_WITH_RX=1— on plain Linuxlibusb the post-fork parent/child race on the shared handle and both
crash with
rtw_read: iostream errorbefore TX begins. Cross-adapter(TX on one adapter, RX on another) is the only configuration that
actually works on regular Linux.
DEVOURER_PID/DEVOURER_CHANNEL/DEVOURER_SKIP_RESETenv varsfor parity with the RX demo.
(
57:42:75:05:d6:00) and log<devourer-tx-hit>on match. A cleansignal for cross-adapter TX validation.
8814AU: TX FIFO bring-up — page allocation, auto-LLT, REG_CR preserve
Three real chip-init bugs the 8812-path init silently no-ops on the 8814:
REG_RQPN/REG_BCNQ_BDNY/
REG_TRXFF_BNDY(256-page TX FIFO model). The 8814 has a 2048-pageTX FIFO and uses 32-bit
REG_FIFOPAGE_INFO_{1..5}_8814A+ 16-bitboundary registers. Port
_InitQueueReservedPage_8814AUsband_InitPageBoundary_8814AUsbfrom upstreamhal/rtl8814a/usb/usb_halinit.c. Verified: HPQ=32, PUB=1912,bndy=0x07F8 after the fix.
free-page linked-list never gets built (page counts advertised but no
actual pages linked). Upstream's
InitLLTTable8814Awrites BIT0 of an8-bit access at 0x208 — that's the wrong bit; the actual trigger
per
hal_com_reg.h:1424isBIT_AUTO_INIT_LLT = BIT(16)of the 32-bitregister. Use the correct BIT(16) trigger as a 32-bit RMW. Verified:
BIT16 self-clears within 2ms, confirming the chip processed it.
observed value first and OR's in our minimum-required bits, instead of
clobbering the whole word. Defensive — on this hardware fw doesn't
set high bits but the read-OR-write shape is the safer pattern.
8814AU: TX-state diagnostic dump + send_packet pre-TX probe + DEVOURER_TX_EP
/ MCUFWDL / TXDMA_STATUS / TXDMA_OFFSET_CHK / HWSEQ_CTRL / TCR / RCR.
One log per register (Logger format helper truncates multi-placeholder
lines).
send_packet: on first call only, log CR / TXPAUSE / TXDMA_OFFSET_CHK/ FWHW_TXQ_CTRL / MCUFWDL / HCIPWR. Surfaces any clobber between
init-end and the actual first TX.
DEVOURER_TX_EP=0xNNoverrides the hardcoded bulk OUT endpoint 0x02for EP-bisection diagnostics without a rebuild.
All diagnostic output is gated behind
CHIP_8814Aor env vars; 8812 pathis untouched at runtime.
Known limitation
8814 TX end-to-end still doesn't work. All three OUT EPs (0x02 / 0x03 / 0x04)
silently time out (
LIBUSB_TRANSFER_TIMED_OUT,actual_length=0). Chipstate at TX time looks correct on every register we've examined — CR=0x00FF,
TXPAUSE=0x00, FW running (MCUFWDL[0]=0x78), queues have pages, auto-LLT
fires, TX descriptor checksum matches upstream byte-for-byte. The remaining
gate is somewhere we haven't dumped yet. Diagnostic infrastructure in
commit 3 is ready for the next investigation.
Test plan
frames received in 18s.
still receive (page allocation + auto-LLT + REG_CR-preserve only
enhance bring-up, none remove or rewrite registers the RX path
requires).
make this a future PR; chip-init fixes in commit 2 are landed
regardless.
🤖 Generated with Claude Code