Summary
Repeated devourer sessions on one adapter progressively degrade high-order
constellation TX while leaving the robust rates untouched. Only a VBUS
power cycle recovers it — libusb_reset, teardown/re-init, and idling do
not.
This is a real deployment bug, not just a bench annoyance: an airborne link
cannot power-cycle its adapter. A drone that restarts its TX process, or runs
a long session, silently loses its top rates with nothing in any log to say so.
Why it is dangerous
It is not a wedge, and that is what makes it easy to misdiagnose. Throughout
the degradation the adapter:
- keeps enumerating and accepting frames;
- reports every frame submitted, zero failures;
- keeps delivering the robust rates at full ratio;
- reports strong RSSI and clean EVM on the frames that do decode (because
only the low-order frames decode, and those are clean).
The signature is indistinguishable from "the link is too weak to carry a denser
constellation". In the investigation that surfaced this, it produced a
completely coherent but wrong conclusion — a peaked delivery-vs-power curve,
the same ceiling on an empty channel (ch14), and the same ceiling across three
different receivers — all of it an artifact of accumulated chip state.
Reproduction
tests/warm_tx_degradation_repro.sh (added alongside this report). It holds one
ground receiver up for the whole run so the reference never moves, then
alternates {probe} and {N warm devourer sessions} on the DUT, and finishes with
two controls.
sudo REGRESS_VBUS_MAP="0bda:8812=3-2.3.4,3;2357:012d=10,2" \
tests/warm_tx_degradation_repro.sh
Two independent runs, RTL8812AU TX -> RTL8822BU ground, ch6, 20 MHz, constant
TX config:
| stage |
MCS7 (64-QAM 5/6) |
MCS1 control |
| cold baseline |
63.3% / 62.6% |
97.7% |
| after 3 warm sessions |
58.1% / 58.1% |
97.2% |
| after 6 warm sessions |
56.3% / 56.6% |
97.3% |
| after 9 warm sessions |
57.4% / 55.2% |
97.1% |
| after 12 warm sessions |
56.3% / 55.1% |
97.2% |
| after 60 s idle, no power cycle |
57.6% / 59.6% |
97.0% |
| after VBUS cold cycle |
64.0% / 61.9% |
97.1% |
The control rate is flat at ~97% the whole way, so this is not ambient drift,
and the recovery is what confirms it: only removing power restores the rate.
The severe form (observed, not yet isolated)
The table above is the mild, reliably reproducible form: ~7 points over 12
sessions. During the original investigation the same adapter reached a far worse
state — MCS5, MCS6 and MCS7 all at exactly 0% delivery while MCS0–MCS4 kept
working normally at ~88%. A VBUS cycle restored MCS7 to 58% at the same channel,
power and inter-frame gap.
That state followed roughly a hundred sessions that also included band switches
(2.4 -> 5 GHz), bandwidth switches (20/40 MHz), flat TX-power index overrides,
and large power offsets in both directions. Plain repetition at fixed
config does not reproduce it, and neither does max-power/max-duty repetition
(WARM_PWR=63 WARM_GAP=0, which the script supports) — that gives the same ~7
point curve. Isolating the aggravating factor is the main open question.
Investigation leads
- The selectivity is the clue. The datapath, USB, descriptors and MAC are
demonstrably fine — the low rates ride the exact same path at full delivery.
What degrades is analog transmit quality, i.e. EVM. That points at
calibration state (IQK / LCK / DPK) or power/thermal tracking, not DMA.
- Not simple thermal. 60 s idle does not recover the plain form. The
max-power variant recovers partially on idle (59.6% vs 55.1%), suggesting a
thermal component stacked on top of a persistent state component.
- Prior art, likely the same root cause. The RTL8814AU "post-use
degradation" wedge (chip stops delivering after a few devourer runs; only
VBUS recovers; libusb_reset and idle do not) looks like the severe end of
this same axis. A proposed deinit-before-init fix was reverted as unvalidated
because the warm gate never fired — devourer issues libusb_reset before
claim, so the chip never presents as "already on". Worth re-examining with
the constellation-selective probe here, which is a far sharper signal than
"wedged / not wedged".
- Candidate fix direction. If it is calibration state, an explicit
de-init (vendor card_disable_flow) or a forced re-calibration on bring-up
should recover it without removing power. That is the outcome that matters
for the field: a software-only recovery path, since the drone cannot
power-cycle.
Impact
- Long-running or restart-prone field links silently lose their top rates.
- Any bench measurement of a rate/modulation ceiling is invalid unless it
cold-cycles per cell — it otherwise measures accumulated chip state. This is
now documented in CLAUDE.md and enforced by default in
tests/nitroqam_waterfall.sh.
Chips
Characterized on the RTL8812AU (Jaguar1). The 8814AU shows the probable severe
variant. Unknown on Jaguar2/Jaguar3/Kestrel — the repro script is
chip-agnostic (DUT_VID/DUT_PID) and running it per generation is the first
concrete task.
Summary
Repeated devourer sessions on one adapter progressively degrade high-order
constellation TX while leaving the robust rates untouched. Only a VBUS
power cycle recovers it —
libusb_reset, teardown/re-init, and idling donot.
This is a real deployment bug, not just a bench annoyance: an airborne link
cannot power-cycle its adapter. A drone that restarts its TX process, or runs
a long session, silently loses its top rates with nothing in any log to say so.
Why it is dangerous
It is not a wedge, and that is what makes it easy to misdiagnose. Throughout
the degradation the adapter:
only the low-order frames decode, and those are clean).
The signature is indistinguishable from "the link is too weak to carry a denser
constellation". In the investigation that surfaced this, it produced a
completely coherent but wrong conclusion — a peaked delivery-vs-power curve,
the same ceiling on an empty channel (ch14), and the same ceiling across three
different receivers — all of it an artifact of accumulated chip state.
Reproduction
tests/warm_tx_degradation_repro.sh(added alongside this report). It holds oneground receiver up for the whole run so the reference never moves, then
alternates {probe} and {N warm devourer sessions} on the DUT, and finishes with
two controls.
sudo REGRESS_VBUS_MAP="0bda:8812=3-2.3.4,3;2357:012d=10,2" \ tests/warm_tx_degradation_repro.shTwo independent runs, RTL8812AU TX -> RTL8822BU ground, ch6, 20 MHz, constant
TX config:
The control rate is flat at ~97% the whole way, so this is not ambient drift,
and the recovery is what confirms it: only removing power restores the rate.
The severe form (observed, not yet isolated)
The table above is the mild, reliably reproducible form: ~7 points over 12
sessions. During the original investigation the same adapter reached a far worse
state — MCS5, MCS6 and MCS7 all at exactly 0% delivery while MCS0–MCS4 kept
working normally at ~88%. A VBUS cycle restored MCS7 to 58% at the same channel,
power and inter-frame gap.
That state followed roughly a hundred sessions that also included band switches
(2.4 -> 5 GHz), bandwidth switches (20/40 MHz), flat TX-power index overrides,
and large power offsets in both directions. Plain repetition at fixed
config does not reproduce it, and neither does max-power/max-duty repetition
(
WARM_PWR=63 WARM_GAP=0, which the script supports) — that gives the same ~7point curve. Isolating the aggravating factor is the main open question.
Investigation leads
demonstrably fine — the low rates ride the exact same path at full delivery.
What degrades is analog transmit quality, i.e. EVM. That points at
calibration state (IQK / LCK / DPK) or power/thermal tracking, not DMA.
max-power variant recovers partially on idle (59.6% vs 55.1%), suggesting a
thermal component stacked on top of a persistent state component.
degradation" wedge (chip stops delivering after a few devourer runs; only
VBUS recovers;
libusb_resetand idle do not) looks like the severe end ofthis same axis. A proposed deinit-before-init fix was reverted as unvalidated
because the warm gate never fired — devourer issues
libusb_resetbeforeclaim, so the chip never presents as "already on". Worth re-examining with
the constellation-selective probe here, which is a far sharper signal than
"wedged / not wedged".
de-init (vendor
card_disable_flow) or a forced re-calibration on bring-upshould recover it without removing power. That is the outcome that matters
for the field: a software-only recovery path, since the drone cannot
power-cycle.
Impact
cold-cycles per cell — it otherwise measures accumulated chip state. This is
now documented in
CLAUDE.mdand enforced by default intests/nitroqam_waterfall.sh.Chips
Characterized on the RTL8812AU (Jaguar1). The 8814AU shows the probable severe
variant. Unknown on Jaguar2/Jaguar3/Kestrel — the repro script is
chip-agnostic (
DUT_VID/DUT_PID) and running it per generation is the firstconcrete task.