Repository navigation
Conversation
The RTL8812CU could not air a single 40 MHz frame on most channels while the same card does HT40 under mainline rtw88. Two faults, both gated on the 8822C so the 8822E's descriptor and DIG stay byte-identical: - The inject descriptor carried DISDATAFB=0 (the Jaguar1 mirror). With USE_RATE=1 the MAC's per-frame rate-fallback lookup consults the fw's per-MACID entry, which an injecting MACID lacks; on the 8822C that wedges the first 40 MHz frame and the TX FIFO fills. The device now passes dis_data_fb=1 on the C die (the vendor's fixed-rate path does). - On a quiet channel the receiver parks below IGI 0x24 in a gain state where the secondary 20 MHz never reads idle, so the MAC holds every 40 MHz frame; busy channels self-heal because received frames re-run the AGC. DIG_MIN_8822C_WIDE 0x26 is pushed into the phydm runtime after every tune (Init/InitWrite/SetMonitorChannel/FastRetune/ FastSetBandwidth) at 40/80 MHz and honoured by every DIG pass. Costs ~6 dB of idle-channel RX sensitivity at those widths on the CU. Measured on 144(-)/52(+)/149(+)/36(+): ~20.5k frames per 50 s run, 0 failures, all received at MCS3 bw 40; HT20 unchanged. Record: docs/experiments/8822c-ht40-tx-stall.md. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PbfYcAbwocHjWbXn9q8tzB
… sent The floor costs ~6 dB of idle-channel RX sensitivity, which a device that only receives at 40 MHz — a CU ground station, whose own control frames are 20 MHz — pays for nothing. Arm it from build_tx_block on the first >= 40 MHz descriptor (one _reg_mu take, the FastRetune precedent), keep it across tunes while the width stays wide, drop it at a narrow width. Bench, ch 144 silent, no knobs: HT40 TX 9091 frames / 0 failed with IGI 0x26 after arming; 20 MHz frames into the 40 MHz tune 9928 / 0 at IGI 0x20; RX-only at 40 MHz stays at 0x20. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PbfYcAbwocHjWbXn9q8tzB
…cost as an estimate Review follow-up to the 8822C HT40 inject fix. - A 40 MHz frame into a 20 MHz tune armed the floor and apply_igi_floor_locked disarmed it again at the narrow width, so every such frame re-took _reg_mu on the send path (txdemo hits it with DEVOURER_TX_RATE=.../40 and no DEVOURER_HOP_BW). Arming now requires the tune to be >= 40 MHz too. - Stop() clears the arm, so a later Init on the same device starts without the floor. - The RX-sensitivity cost was quoted as "~6 dB". It is arithmetic from the 1 dB IGI step, not a measurement, and 6 dB holds only over the DFS floor; on a non-DFS channel (36 and 149 in the result table) it is 4-8 dB over the coverage window. Header, experiment doc and CLAUDE.md now say so. - src/jaguar3/CLAUDE.md keeps the fact and points at the headers and the experiment doc instead of restating them. No hardware re-run: the arming change only removes a narrow-tune case that never applied the floor anyway. ctest 81/81. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Five 30 s cells on silent 144(-)/149(+), both adapters local: - CU HT40: 0 failed, witness 99.6 % at MCS3 bw:1, floor armed at 0x26. - 40 MHz frames into a 20 MHz tune leave the floor unarmed (0x20). - HT20 control: unchanged. - 8822E HT40: 0 failed, 99.1 % at bw:1, IGI 0x20, as is the RX-only CU witness. Near-field single runs. The send rate is gap-limited, so this does not measure the removed per-frame lock. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
PR Summary by QodoFix 8822C 40 MHz frame injection stalls
AI Description
Diagram
High-Level Assessment
Files changed (7)
|
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Code Review by Qodo
1.
|
…ssion-scoped floor arm - DISDATAFB=1 was written on every 8822C frame, which silently turned the fw retry ladder (OpenIPC#362/OpenIPC#371, RetryFallback::Default) off at 20 MHz too. It now covers 40/80 MHz frames only. Measured on the CU, unACKed unicast MCS3 limit 8: - 20 MHz: MCS3 x4 > MCS2 > 6M restored, 1223/1224. - 40 MHz: pinned at MCS3, 1208/1209. - 20 MHz frames with DISDATAFB=0 on a 40 MHz tune: 14163 / 0 failed, so the wedge keys on frame width. DeviceConfig.h's RetryFallback note says the 8822C's wide frames have no ladder at either setting. - The floor arm is now "this session has sent a wide frame" (_wide_tx_seen): - Set once, published after the floor is applied, cleared by Init, InitWrite and Stop. - The floor follows the tuned width, read under _reg_mu on both sides. - A retune racing the first wide frame can no longer skip it, and a re-Init no longer inherits it. - A 40 MHz frame on a 20 MHz tune still takes the lock once per session. - Dropping the floor clamps IGI back into the channel's DIG window at once, instead of leaving 0x26 until the next tick. Keeping it at 0 touches no register, so the 8822E path is unchanged. Not exercised on air: the drop clamp and the race. ctest 78/78. HT40 CU and EU and HT20 cells re-run, 0 failed (experiment doc). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ssion-scoped floor arm - DISDATAFB=1 was written on every 8822C frame, which silently turned the fw retry ladder (OpenIPC#362/OpenIPC#371, RetryFallback::Default) off at 20 MHz too. It now covers 40/80 MHz frames only. Measured on the CU, unACKed unicast MCS3 limit 8: - 20 MHz: MCS3 x4 > MCS2 > 6M restored, 1223/1224. - 40 MHz: pinned at MCS3, 1208/1209. - 20 MHz frames with DISDATAFB=0 on a 40 MHz tune: 14163 / 0 failed, so the wedge keys on frame width. DeviceConfig.h's RetryFallback note says the 8822C's wide frames have no ladder at either setting. - The floor arm is now "this session has sent a wide frame" (_wide_tx_seen): - Set once, published after the floor is applied, cleared by Init, InitWrite and Stop. - The floor follows the tuned width, read under _reg_mu on both sides. - A retune racing the first wide frame can no longer skip it, and a re-Init no longer inherits it. - A 40 MHz frame on a 20 MHz tune still takes the lock once per session. - Dropping the floor clamps IGI back into the channel's DIG window at once, instead of leaving 0x26 until the next tick. Keeping it at 0 touches no register, so the 8822E path is unchanged. Not exercised on air: the drop clamp and the race. ctest 78/78. HT40 CU and EU and HT20 cells re-run, 0 failed (experiment doc). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…only, session-scoped floor) into the fork Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Folds the original table and both re-test sections into one: GS and local benches in one table, superseded intermediate rows dropped, the retry ladder and the limits stated once. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The problem
The RTL8812CU (8822C) could not air a single 40 MHz injected frame on most 5 GHz channels, though the same card does HT40 under mainline rtw88. On 144(-), 36(+) and 149(+), bulk-OUT accepted 257 frames and then failed with rc=-7, and nothing went on air. At the abort the TX FIFO was full (
LQ 64/0 PUB 1745/19): the MAC never completed the first 40 MHz frame. HT20 was unaffected.There were two independent faults, and fixing either alone is not enough.
The change
Both parts apply only to the 8822C. The 8822E's descriptor and DIG are byte-identical to before.
fill_data_tx_desc_8822c, newdis_data_fbargument).DEVOURER_TX_RETRY_FALLBACKsetting, andDeviceConfig.hsays so.DIG_MIN_8822C_WIDE 0x26,PhydmRuntimeJaguar3::set_igi_floor).Stop()clear the arm._reg_muby every tune (Init / InitWrite / SetMonitorChannel / FastRetune / FastSetBandwidth). It is on at 40/80 MHz. At a narrower width it drops, with IGI clamped straight back into the normal DIG window._reg_muonce per session and never on the steady-state send path. The flag is published only after the floor is applied, so neither a racing retune nor a concurrent sender can skip it.Record, including the dead ends (firmware RA_INFO in every layout, firmware version, IQK, TX power, CCA, AGC lower bound):
docs/experiments/8822c-ht40-tx-stall.md.Measured
txdemo on the CU, with an 8812EU witness on rxdemo at the same channel and width. 1 kB QoS-data frames, MCS3/40/LDPC, 50 s per run, no knobs. "Aired" means CRC-ok frames the witness decoded with
bw:1.Before the change, the same 40 MHz runs aired nothing.
How each half was isolated:
The counterpart: the floor costs idle-channel RX sensitivity at 40/80 MHz on a CU that transmits wide. That cost is estimated from the 1 dB IGI step, not measured: 6 dB over the DFS floor 0x20, and 4–8 dB over the 0x1e..0x22 coverage window on a non-DFS channel. Each row is a single 50 s run. The effect size (0 vs ~20k) is far outside probe-to-probe noise, but the 36(+) row's lower witness count (96.3% vs ~99.5% elsewhere) was not repeated.
Re-test on the final code (both adapters local, near-field, silent channels confirmed by an 8 s scan beforehand, 30 s per cell):
After the review (f87521b), same bench, silent 144:
Retry ladder,
tests/retry_ladder_probe.shshape: unACKed unicast, MCS3, limit 8.Headless: ctest full 78/78, without Jaguar3 78/78, 8822C-only 69/69.
Not covered
🤖 Generated with Claude Code