Skip to content

TX degrades across warm sessions: high-order constellations die, only a VBUS power cycle recovers (a drone cannot power-cycle in flight) #348

Description

@josephnef

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions