Skip to content

Follow-ups left open by the 8822B DFIR and J3 runtime-thread reviews (#497, #498) #499

Open

Description

@josephnef

Things the #497 and #498 reviews measured but did not settle. Bench for all of them: an 8812EU (Jaguar3, 0bda:a81a) transmitting and an 8812BU (8822B cut 3, CF-924AC 0bda:b812) receiving.

1. Does Jaguar3 TX go silent with the runtime thread off, given longer runs or the 8822C? (#498)

src/jaguar3/CLAUDE.md says sustained 5 GHz TX needs the coex runtime thread; without it the coex firmware silences the antenna. On the 8822E I could not reproduce that within 22 s. TX-only, ch36 MCS1/20, 10 000 frames:

rep 1 rep 2
thread on (default) 99.4 % 99.2 %
DEVOURER_J3_RUNTIME=0 99.5 % 99.4 %

Not tested: runs of minutes rather than seconds, the 8822C (8812CU/8822CU), and the upper 5 GHz channels, where pwr_track matters. If the silencing does not reproduce, the CLAUDE.md claim should be narrowed. If it does, the j3_runtime_thread docs should say after how long and on which die.

2. Is MCS7 on this pair really worse at 20 MHz than at 40 MHz?

Same pair, same channel (ch36), same session, 1500 frames per cell:

The 20 MHz spread is far above the usual ±3-point probe noise, and the 20 MHz result is worse than the 40 MHz one, which is backwards. One unexplored lead: in the earlier runs at this distance the rx.txhit RSSI read 102–104, i.e. near-field. At 20 MHz the same TX power is concentrated in half the bandwidth, so this may be receiver saturation, which would show as poor EVM rather than poor RSSI. Check EVM and repeat at more distance (or lower TX power) before believing the number.

3. Re-qualify the 8822B b812 for HT40 on 2.4 GHz

After #497 the b812 is flat up to MCS7 on ch36 HT40 (88.7 / 89.9 / 89.2 / 89.0 / 93.5 / 96.6 % across MCS1/3/4/5/6/7). It was already qualified at 20 MHz. ch6 HT40 is still unmeasured: the 8812EU module is wired with 5 GHz antennas and is not a usable 2.4 GHz transmitter (ch6, 20 MHz: 6M 29.5 %, MCS1 0 %). Repeat the ladder with a transmitter that works on 2.4 GHz.

4. Does Jaguar1 have the same wide-RX hole?

Before #497, rxdemo with DEVOURER_BW=40 delivered nothing on Jaguar2. The 8822B half of that was its RX DFIR being left in the 20 MHz setting (0 % → ~96 % at VHT80). The 8821C path already switched the DFIR by width. Jaguar1 (8812AU/8814AU/8821AU) has not been checked. Run the same A/B: an 8812EU sending HT40/VHT80 on ch36 into an 8812AU at DEVOURER_BW=40/80.

Activity

  1. josephnef commented on Oct 26, 2026

    @josephnef
    CollaboratorAuthor

    Item 4 (Jaguar1 wide RX): no hole on 5 GHz. The 8812EU sent HT40/VHT80 on ch36 into an 8812AU (0bda:8812) running current master (f4a79e5) at DEVOURER_BW=40/80. 1500 frames per cell, 2 reps:

    Rate rep 1 rep 2
    MCS1/20 (control) 98.7 % —
    MCS1/40 98.3 % 98.5 %
    MCS4/40 98.1 % 98.4 %
    MCS7/40 94.0 % 97.4 %
    VHT1SS MCS1/80 88.0 % 79.9 %
    VHT1SS MCS4/80 88.1 % 85.5 %
    VHT1SS MCS7/80 94.9 % 85.3 %

    These frames are genuinely wide: before #497, the 8822B decoded 0 % of the same 80 MHz stream. Jaguar1 does not need the DFIR fix.

    Scope: ch36 only, one 8812AU. The 8814AU, the 8821AU and 2.4 GHz HT40 are unchecked. 2.4 GHz waits on item 3's transmitter, because the 8812EU module cannot transmit there. The VHT80 rows scatter more (80–95 %) than HT40 does. With only 2 reps I am not reading that as a width effect.

  2. josephnef commented on Oct 26, 2026

    @josephnef
    CollaboratorAuthor

    Item 3 (b812 HT40 on 2.4 GHz) can't be qualified yet. It turned up two receive bugs instead. TX was a TP-Link Archer T3U (8822B, 2357:012d), ch6 HT40+, master f4a79e5.

    A. 8822B HT40 RX on 2.4 GHz sometimes goes deaf for a whole session. 10 of 34 b812 sessions decoded 0 of the HT40 stream, at every rate. Every other session ran ~62–76 %. On 5 GHz (ch36 HT40/VHT80) there were 0 zero sessions in 30.

    • Not the TX. In 8 B210-instrumented sessions (99 % occupied bandwidth at the 2447 MHz HT40 centre), zero sessions 3 and 8 radiated 35.9 / 36.7 MHz, the same as the good sessions (~35.9 MHz; noise baseline 45.2 MHz). Zero session 5 read 28.7 MHz, so that one is ambiguous.

    • What deaf looks like. The RX loop stays alive and keeps logging the ambient 20 MHz beacons (~480 frames in 30 s vs ~120 000 in a good session), but no HT40 frame gets through.

    • Ruled out:

      • The 2440 MHz NBI/CSI spur-notch decision (notch on in a zero session, off in a good one).
      • Anything in the info-level logs (identical between good and zero sessions).
      • Bring-up-end BB/RF state. A DEVOURER_BB_DUMP=1 diff over 10 sessions (2 zero) found no stable register that separates them, only counters/timers that vary in every session.

      So the trigger comes after bring-up or sits outside the dumped state.

    • In good sessions the receiver is flat, not on a cliff: MCS1 74/76, MCS3 74/66, MCS4 70, MCS5 67/69, MCS6 76, MCS7 70 %. On this busy channel the MCS1/20 control was 79 %. Qualification should wait until A is fixed: a quarter of sessions reading 0 makes any single delivery number meaningless.

    B. Jaguar1 (8812AU) HT40 RX on 2.4 GHz: 0 % in 12 of 12 sessions, MCS1–MCS7, same T3U stream. The same 8812AU decodes:

    • the T3U at ch6 / 20 MHz: 60.4 / 61.9 %;
    • HT40 on ch36: 94–98 % (comment above).

    If B were the same intermittent failure as A, twelve zeros in a row would be ≈0.29¹² ≈ 4·10⁻⁷, so this is a separate, deterministic hole. That means item 4's "no Jaguar1 wide-RX hole" holds for 5 GHz only.

  3. josephnef commented on Oct 26, 2026

    @josephnef
    CollaboratorAuthor

    Correction to the previous comment: bug A is on the TX side, not the RX side. Vendor-driver control for bug B.

    Same T3U stream (ch6 HT40+, devourer txdemo), received by two independent receivers in parallel: an 8812AU on Realtek's own driver (reference/rtl8812au, 88XXau_ohd.ko, monitor, tcpdump on the canonical SA) and the b812 on devourer. 1500 frames per session:

    cell rep 8812AU, vendor driver b812, devourer
    ch6 HT40+ MCS1/40 1 1 (0.1 %) 0
    2 1 (0.1 %) 0
    3 843 (56.2 %) 1132 (75.5 %)
    ch6 HT40+ MCS7/40 1 1 (0.1 %) 0
    2 909 (60.6 %) 1093 (72.9 %)
    3 787 (52.5 %) 970 (64.7 %)
    ch36 HT40+ MCS1/40 (control) 1–3 95.7 / 97.1 / 94.6 % 96.5 / 96.9 / 95.4 %
    ch6 HT20 MCS1 (control) 1 70.4 % 86.3 %
    • A. The zero sessions are on the T3U side. Two different receiver chips, on two different drivers, read zero in exactly the same sessions. That puts the fault in the 8822B's devourer TX of HT40 on 2.4 GHz, which intermittently airs a 40 MHz-wide but undecodable signal. My B210 measurement showed only that the energy occupies ~36 MHz, not that the frames can be decoded, and I over-read it as "TX fine". The RX-side diagnostics in the previous comment (identical logs, no separating BB register) are consistent with this: the receiver was never the variable.
    • B. Confirmed as a devourer bug. The 8812AU decodes ch6 HT40 at 52–61 % on the vendor driver whenever the transmitter airs a good stream, but 0 % in 12 of 12 sessions on devourer. With TX failing in ~30 % of sessions, 12 zeros by chance would be ≈0.3¹² ≈ 5·10⁻⁷. The receive hardware works; the bug is in devourer's Jaguar1 2.4 GHz HT40 RX setup. Next step: diff devourer's 2.4 GHz 40 MHz BB/RF state against the vendor driver's on this unit.
  4. josephnef commented on Oct 26, 2026

    @josephnef
    CollaboratorAuthor

    Bug B root cause found and fixed locally (not yet pushed).

    Jaguar1's rtw_get_center_ch used a hand-written lookup table for the 40 MHz centre that ignored the HT40 offset. On 2.4 GHz it only knew primaries 4 and 8; every other primary fell through and stayed uncentred. So ch6 HT40+ tuned the RF synthesizer to ch6 instead of ch8, 10 MHz low. Every HT40 frame was lost, while 20 MHz on the same channel was fine. The table was also wrong on UNII-3 (153→155, 161→163) and for the non-default offset on the pairs it did list.

    Evidence, from the same 8812AU at ch6 HT40+. BB/MAC bandwidth registers (0x483, 0x668, 0x838, 0x8ac, 0xa08) were already identical to the vendor driver. RF 0x18 was the one structural difference:

    RF[A/B] 0x18
    vendor driver 0x07408 (BW 40, channel byte 8)
    devourer, before 0x07406 (BW 40, channel byte 6)
    devourer, fix 0x07408; HT40− gives 0x07404

    The fix uses the vendor's offset rule (UPPER → primary − 2, otherwise + 2, the rule Kestrel already uses) and drops the table. On air: T3U TX, the 8812AU on devourer as DUT, and the b812 as an independent witness in parallel. 1500 frames, 3 reps:

    cell 8812AU (fix) b812 witness vendor driver, earlier
    ch6 HT40+ MCS1/40 45.5 / 51.7 / 35.9 % 74.9 / 77.5 / 57.3 % 56.2 %
    ch6 HT40+ MCS7/40 53.9 / 52.2 / 0.0 %¹ 71.3 / 70.7 / 0.0 %¹ 52.5–60.6 %
    ch6 HT40− MCS1/40 53.5 / 54.4 / 52.7 % 73.1 / 65.5 / 70.7 % —
    ch36 HT40+ MCS7/40 95.5 / 96.3 / 95.9 % 94.7 / 96.9 / 95.3 % —
    ch40 HT40− MCS7/40 93.7 / 96.5 / 96.6 % 86.1 / 95.7 / 96.0 % —

    ¹ Both receivers read zero together, i.e. the T3U TX-side failure (bug A), not this bug.

    On 2.4 GHz devourer now lands roughly where the vendor driver does on this unit, from 0 % before. 5 GHz is unchanged. ctest passes 86/86.

    Still unchecked: the 8814AU and 8821AU (they share this function, so the fix covers them, but neither was measured), and 2.4 GHz channels other than 6.

  5. josephnef commented on Oct 26, 2026

    @josephnef
    CollaboratorAuthor

    Bug B fix is in #500. Review turned up a second edge, also fixed there: offset arithmetic alone left the 2.4 GHz band at the grid edges (ch13 HT40+ gave centre 15; ch1 HT40− wrapped to 255). Requests now fit 1–13, and a FastRetune hop back from the edge restores the requested side. Validated on air in both directions: the 8812AU transmitting at ch13 / ch1 decoded 87–91 % by two 8822B receivers.

  6. josephnef commented on Oct 26, 2026

    @josephnef
    CollaboratorAuthor

    Bug A (8822B HT40 TX intermittent on 2.4 GHz): root cause found. The fix is not validated, so nothing is shipped.

    Mechanism. Devourer's 8822B bring-up runs the driver-side LCK (HalJaguar2::do_lck, a port of _phy_lc_calibrate_8822b). On the TP-Link T3U (2357:012d), it leaves the synthesizer on a bad calibration code in roughly 40–50 % of bring-ups. The chip then radiates a ~36 MHz-wide signal that no receiver decodes. The same failure hits the T3U's receive side: as a witness it missed 6 of 20 sessions.

    Evidence. The T3U transmitted ch6 HT40+ MCS1/40. Two independent witnesses received: an 8812AU and the b812. I read the chip's live state with chipstate --no-claim mid-flood:

    • Indicator. The low byte of RF_A 0xb2 is the only stable register that separates the sessions: ≤ 0x91 when bad, ≥ 0x93 when good. Read 3 s into each session, it predicted 32 of 32 verdicts prospectively.
    • Not a lever, itself. The low bits are read-only status: an LSSI write leaves the readback unchanged and does not recover TX. Re-triggering the per-channel synth calibration (RF 0xb8[19], 5×) does not change the code either.
    • Causal test. Re-running the full LCK sequence mid-session recovered 3 of 3 bad sessions (code → 0x9a, both witnesses decoding). Across 34 earlier bad sessions, none recovered on its own.

    Vendor. Realtek's driver does not run this LCK on the 8822B in normal operation. Power tracking excludes the 8822B explicitly ("Use RTLCK, so close power tracking driver LCK"), and halrf_lck_trigger is otherwise reachable only from CONFIG_DBG_RF_CAL. Devourer has run it at bring-up since the original 8822B port.

    Candidate fix (not shipped): drop the 8822B bring-up LCK and rely on RTLCK, as the vendor does. Why it is unproven:

    • Warm T3U, no LCK: 20/20 good, but every session read 0x2249a, the code the previous re-LCK left behind. Jaguar2 does not power the chip down at teardown, so this proves nothing.
    • Cold b812 (VBUS-cycled every session), master vs no-LCK: 0 bad TX sessions in 20 either way. This unit's codes sit at 0x78–0x7b and it does not show the failure, so it cannot validate the fix.
    • The decisive test is still open: a cold A/B on the T3U itself. Its current root port cannot cut VBUS (state survives a uhubctl cycle), so it has to move to a port with per-port power switching first.
  7. josephnef commented on Oct 26, 2026

    @josephnef
    CollaboratorAuthor

    Correction and update on bug A. The "drop the bring-up LCK" candidate fix is withdrawn.

    Naming. I called the failing adapter an "Archer T3U". That name came from the lsusb ID lookup and INVENTORY.md slot #14, not from the hardware. The device reports only Realtek's generic strings, and per the bench owner there is no T3U on the bench. The unit is a TP-Link-VID 8822B adapter, 2357:012d. All measurements above stand; only the name was wrong.

    New data. The adapter was moved off the PC root port (bus 10 port 2) onto a hub port with real per-port power switching (3-2.3 port 2, verified: chip state reads the 0xEA power-off fill after a cycle). TX ch6 HT40+ MCS1/40; the b812 witness decodes ~4600–4900 frames every good session.

    condition master (bring-up LCK) no LCK
    cold, VBUS-cycled each session, USB 2 10/10 good (0xb2 code 0x97 / 0x9a) 9/10 good; 1 dead with 0xb2 = 0x23c00 (looks uncalibrated)
    warm, back-to-back, USB 2 12/12 good (0x98–0x9b) 12/12 good (carried-over 0x99)
    warm, USB 3 SuperSpeed (switched on the same port via HalMAC set_usb_mode replayed with chipstate --poke) 12/12 good (0x98–0x99) —

    What this changes:

    • Not reproduced off the root port. On the root port the same adapter and build failed ~45 % of sessions, with codes 0x86–0x91; good sessions there read 0x93–0x99. On the hub port it never failed in 34 master sessions, cold or warm, at USB 2 or USB 3.
    • USB speed and warm state are ruled out as the trigger. What remains is something about that root port: supply, thermal environment or physical position. The whole code distribution sat lower there. I have not tested which; moving it back and varying one at a time would be next.
    • Dropping the LCK is not a fix. Without it, one cold bring-up in 10 came up dead with an uncalibrated-looking code. The bring-up LCK (which the vendor does not run) does protect cold starts on this unit.
    • Still valid: the 0xb2 indicator and the mid-session re-LCK recovery (3/3) from the root-port runs.
  8. josephnef commented on Oct 26, 2026

    @josephnef
    CollaboratorAuthor

    Naming follow-up: the bench owner has identified the 2357:012d adapter from its product photo as a TP-Link Archer T3U (the model is printed on the USB plug). The "Archer T3U" name in the earlier comments, and INVENTORY.md slot #14, were correct. Disregard the naming correction in my previous comment; the rest of that comment (results off the root port, fix withdrawn) stands.

  9. josephnef commented on Oct 26, 2026

    @josephnef
    CollaboratorAuthor

    Item 3 done: b812 re-qualified for HT40 on 2.4 GHz. The T3U transmitted from the hub port, and its synth code was checked in every session to confirm a healthy TX. ch6 HT40+, 1500 frames × 2 reps:

    MCS1 MCS3 MCS4 MCS5 MCS6 MCS7
    75.2 % 77.8 % 78.9 % 75.3 % 76.2 % 69.8 % (65.9–73.7)

    That passes the ground_station_qualify 0.85 flat rule at 0.88, borderline at MCS7. ch6 is busy (MCS1/20 control: 84–86 %), so the ~76–79 % plateau is the channel, not the receiver.

    New lead for bug A. Both MCS1/20 control sessions landed the T3U on RF_A 0xb2 code 0x8f, in my "bad" range, yet delivered 84–86 %. So a low code is not harmful at 20 MHz, and it occurs on the hub port too. The code appears to track the tuned frequency: ≈0x8f at 2437 MHz (ch6 at 20 MHz) versus 0x97–0x9b at 2447 MHz (the ch6 HT40+ centre). The bad root-port HT40 sessions read 0x86–0x91, which looks like a synthesizer calibrated near the primary channel rather than the 40 MHz centre. That would make the failure a calibration/tuning ordering race rather than a property of the port. Next check: compare RF18 and the 0xb2 code in the bring-up sequence around do_lck against the final tuned centre, on the root port.

  10. josephnef commented on Oct 26, 2026

    @josephnef
    CollaboratorAuthor

    Bug A: instrumented bring-up refutes the "calibrated at the primary" hypothesis. The T3U was on 9-1.3 (USB 2, behind a 045b:0209 hub), not the original failing root port 10-2. 16 warm sessions, ch6 HT40+, an instrumented do_lck, b812 verdicts:

    • Failure did not reproduce: 16/16 good (1249–1519 / 2000 frames).
    • RF A 0x18 at LCK time is 0x00808 in every session: channel byte 8, the HT40+ centre. The LCK calibrates at the correct frequency, so the "calibrated at the primary" idea is wrong.
    • The LCK never completes. After the recover write, RF18 reads back 0x18808 (LCK-start bit 15 still set), matching the TIMEOUT log in every session.
    • Its own result is not what TX runs with. Right after do_lck, RF_A 0xb2 reads 0x22588–0x22596. Mid-flood it reads 0x2249a in every session, so a later bring-up step or the re-enabled RTLCK (0xc4 = 0x81402) moves it. The bad root-port sessions sat at 0x2248c–0x22491 mid-flood, i.e. that later correction landed differently there.

    Open: reproducing needs the original port (10-2), plus 0xb2 sampled at every bring-up step after do_lck to find which step sets the final code.

  11. josephnef commented on Oct 26, 2026

    @josephnef
    CollaboratorAuthor

    Bug A: per-step instrumentation, USB 3, still not reproduced. The T3U was switched to SuperSpeed on its current socket. That socket enumerates as 10-1.3 (behind the 045b hub on root port 1), not 10-2 where the failures were recorded, though it is the same xHCI controller at the same 5 Gbps. 16 warm sessions, ch6 HT40+, RF_A 0xb2 logged after each bring-up step:

    step 0xb2
    after do_lck 0x22590–0x225b0
    after IQK, and every later step through end of InitWrite 0x22498/0x22499, unchanged
    mid-flood same as after IQK
    • 16/16 good (1083–1449 / 2000 frames on the b812).
    • The final synth code is set during IQK. IQK's LO retune overwrites the LCK result, and nothing after IQK changes it. The bad root-port sessions (mid-flood 0x2248c–0x22491) must therefore have come out of IQK low.
    • Cannot separate port from time. Across ~110 sessions today on hub ports, 9-1.3 and now 10-1.3 (USB 2 and USB 3, cold and warm), the failure has not recurred once. It was ~45 % on 10-2 earlier today, so the trigger is either that socket or something that has changed since (e.g. ambient temperature).

    Next step if this is resumed: put it on 10-2 exactly, and capture IQK's own LO-related registers around the retune.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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