T1 phydm-runtime residuals: DIG floor + TX BB-swing thermal-meter pwrtrk#65
Merged
Conversation
T1 canary diff residual #1 of 2 from PR #64. Upstream phydm runs DIG (Dynamic Initial Gain) from a watchdog timer and walks 0xc50/0xe50 down to 0x1c on all Jaguar chips (phydm_dig.c sets dm_dig_min = 0x1c for ODM_RTL8812 | RTL8814A | RTL8821 | RTL8822B). Devourer has no phydm watchdog so its IGI was stuck at the BB-init seed 0x20 — about 4 dB less RX sensitivity than the kernel driver in clean conditions. Cross-checked against /tmp/kernel-canary.txt (aircrack-ng/88XXau on ch6, same dongle): kernel reads BB 0xc50/0xe50 = 0x0000001C post-init; devourer now matches byte-for-byte (previously 0x20). Also documents the second canary residual (0xc1c bits 31:21, phydm TX BB-swing thermal compensation, kernel value 0x23E) inline on both sides of the canary tooling. Closing that one would require porting ~2800 LOC of phydm power-tracking + a watchdog timer; the divergence itself is benign (0 dB devourer vs +1 dB warmed-kernel) and is now explicitly flagged in the diff oracle so the next reader doesn't chase it as a real init bug. Verified RX path still works after the change: WiFiDriverDemo at ch6 captures frames within seconds, no init failures. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Closes T1 canary residual #2 of 2 — BB 0xc1c bits 31:21 (and the path-B equivalent 0xe1c). The previous commit annotated this as out-of-scope; that was wrong. T1's goal is byte-for-byte parity with the kernel reference, and 0xc1c is part of it. Port covers: - The 12 USB delta_swing tables from upstream's `halhwimg8812a_rf.c:txpowertrack_usb` (per-band, per-RF-path, per-temperature-direction lookups, [3][30] for 5G sub-bands). - `tx_scaling_table_jaguar` (37-entry BB-swing table covering -12 dB to +6 dB in 0.5 dB steps). - `odm_txpowertracking_thermal_meter_init` — seeds default_ofdm_index from the current 0xc1c[31:21] value (24 for a 0 dB BB-init seed). - `odm_txpowertracking_callback_thermal_meter` + `odm_pwrtrk_method` + `odm_tx_pwr_track_set_pwr8812a` MIX_MODE branch — read RF[A] [0x42][15:10], fold into a 4-sample rolling average, compute delta vs the EFUSE thermal baseline, walk the channel/band- specific delta_swing table, clamp to the pwr_tracking_limit of 26 (+1 dB; same default upstream uses when tx_rate is unknown), and write `tx_scaling_table_jaguar[final_idx]` to 0xc1c[31:21] and 0xe1c[31:21]. - `odm_clear_txpowertracking_state` — called from `phy_SetBBSwingByBand_8812A` after the BB-swing base is rewritten, mirroring upstream. Without this hook the next pwrtrk tick sees delta_abs==0 (thermal unchanged since last tick) and short-circuits the re-apply, leaving 0xc1c stuck at the BB-init base after every channel-set. Helpers intentionally omitted because they're not reachable from devourer's monitor-mode RX/TX path: by-rate `pwr_tracking_limit` table (we always see tx_rate==0xFF), tx-AGC remnant compensation (final_idx is clamped to pwr_tracking_limit), IQK/LCK retrigger on thermal delta (IQK is done at init only), CCK / xtal-offset / DPK paths, 8814A path-C/D (separate port). Verification (8812AU dongle 0bda:8812, ch6, post-init): Pre-port: BB 0xc1c = 0x40000003 (0x200 / 0 dB) Post-port: BB 0xc1c = 0x47C00003 (0x23E / +1 dB) Kernel ref: BB 0xc1c = 0x47C00003 — byte-for-byte match. Path-B 0xe1c likewise. Remaining canary divergences against /tmp/kernel-canary.txt are all runtime ephemeral state (MAC TBTT counters, RF[A][0x42] thermal sample timing, etc.) — not init bugs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 tasks
josephnef
added a commit
that referenced
this pull request
Jun 2, 2026
## Summary Port of upstream phydm's IQK (`phy_iq_calibrate_8812a` → `_iqk_tx_8812a`) for RTL8812AU. Closes the IQK side of T1 canary divergence vs `aircrack-ng/88XXau`: - **BB 0x8b0**: `0x00000642` matches kernel byte-for-byte (was `0x00000618` pre-port — IQK side effect we'd been mis-attributing as static init drift). - IQK output regs (`0xc10`, `0xccc`, `0xcd4`, `0xe10`, `0xecc`, `0xed4`) now get calibrated values; previously held BB-init seeds. - Convergence: TX A_done=1 B_done=1, RX A_done=1 B_done=1 with 0-1 retries per path. ## Wiring - `HalModule::rtl8812au_hal_init` arms `_needIQK = true` post-RF-config via new `RadioManagementModule::ArmIQKOnNextChannelSet`. - `phy_SwBand8812` arms `_needIQK = true` on band transitions (2.4G ↔ 5G). - `phy_SwChnlAndSetBwMode8812` calls `_iqk.Calibrate()` when `_needIQK` is set. - Env knobs: - `DEVOURER_FORCE_IQK=1` — run IQK on every channel-set (canary-diff workflow). - `DEVOURER_DISABLE_IQK=1` — emergency escape hatch. ## Scope **In:** `_phy_iq_calibrate_8812a` end-to-end (backup → run → restore), `_iqk_tx_8812a` TX-tone + RX-tone calibration loops with ±4 averaging convergence over up to 10 cal iterations per path, `_iqk_backup_*` / `_iqk_restore_*` for MAC/BB/RF/AFE state, `_iqk_configure_mac_8812a`, `_iqk_tx_fill_iqc_8812a` / `_iqk_rx_fill_iqc_8812a`. **Out (not reachable from devourer's monitor-mode init):** FW-offload IQK (no H2C mailbox), per-channel `iqk_matrix_reg_setting[]` cache, VDF/VHT-160, LC calibration, DPK (`_phy_dp_calibrate_8812a`, separate ~700 LOC; that's where BB 0xc90 and residual RF[A/B] 0x00 divergence come from). ## Bug found during validation: 5GHz TX regression First matrix run with IQK enabled surfaced a regression — 8812AU TX at ch36 dropped from `6500/6500 ✓` to `0/6500 ✗`. Root cause was a subtle porting bug in commit `b4b1038`: Upstream uses `odm_get_bb_reg(dm, 0xd00, 0x07ff0000) << 21` to read the 11-bit IQK output. `odm_get_bb_reg` **right-shifts by the mask offset (16) before returning** — devourer's `phy_query_bb_reg` matches this contract, but my naive port used `(rtw_read32(0xd00) & 0x07ff0000) << 21` which leaves the value at bits 16:26, then shifts to positions 37:47 — UB in 32-bit int, in practice yields 0. All 8 TX/RX read sites had the bug → every IQK sample was 0 → convergence "succeeded" with both samples == 0 → FillIQC wrote X=0 instead of either calibrated or default X=0x200 → 5GHz TX broken. Fix: insert the missing `>> 16` to match `odm_get_bb_reg`'s shift-down semantics. The lesson is now captured in kaeru (`Realtek phydm porting trap — odm_get_bb_reg returns shifted-down value`). ## Test plan Full matrix in VM mode across 3 channels with IQK default-on: - [x] **ch6**: 22/24 ✓ — identical to PR #65 baseline. Only fails are pre-existing 8814 TX-gate (issue #36). - [x] **ch36**: 8812-dev TX cells restored — `8812-dev → 8821-ker = 6440/6500 ✓`, `8812-dev → 8814-ker = 5870/6500 ✓` (vs `0/6500` pre-fix). All other cells match master baseline. Pre-existing failures unchanged (8814 TX-gate, 5G dev-dev gap, 5G UNII-1 8814 RX). - [x] **ch100**: matches master baseline pattern. Pre-existing UNII-2/3 receiver asymmetries unchanged. - [x] `DEVOURER_DUMP_CANARY=1` at ch6: `BB 0x8b0 = 0x642` matches kernel byte-for-byte. - [x] RX smoke test: frames received within seconds, no init failures. ## Commits 1. `6027fe9` Initial IQK port (env-gated due to regression). 2. `b4b1038` Fix mask-extract bug — root cause of 5GHz TX regression. 3. `af97973` Flip IQK trigger back to default-on after fix verified. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- 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
Closes the last two T1 canary divergences from PR #64 by porting the relevant phydm runtime loops directly into devourer:
phydm_dig.c:dm_dig_min = 0x1cfor ODM_RTL8812 | RTL8814A | RTL8821 | RTL8822B). Devourer had no watchdog, was stuck at the BB-init seed 0x20 (~4 dB less sensitive). Pre-converged to the documented floor at init.tx_scaling_table_jaguarfromodm_txpowertracking_callback_thermal_meterbased on RF[A][0x42] thermal-meter reads. Full port of the loop + the 12g_delta_swing_table_idx_mp_*_txpowertrack_usb_8812alookup tables.odm_clear_txpowertracking_statehooked intophy_SetBBSwingByBand_8812Aso the next tick re-applies after channel-set rewrites the BB-swing base.Helpers omitted because they're not reachable from devourer's monitor-mode RX/TX path: by-rate
pwr_tracking_limittable (devourer always seestx_rate==0xFF), tx-AGC remnant compensation (final_idx is clamped to pwr_tracking_limit), IQK/LCK retrigger on thermal delta, CCK / xtal-offset / DPK paths, 8814A path-C/D.Canary diff vs kernel reference (
aircrack-ng/88XXauon ch6)0x0000001C0x000000200x0000001C✓0x0000001C0x000000200x0000001C✓0x47C000030x400000030x47C00003✓0x47C000030x400000030x47C00003✓Remaining canary divergences against
/tmp/kernel-canary.txtare runtime ephemeral state only — MAC TBTT/queue counters, RF[A][0x42] thermal sample timing, MAC 0x550/0x560 beacon-window state. Not init bugs.Test plan
Full regression matrix vs PR #64 baseline (
5b7fc12) — VM mode, three channels, all three adapters (8812AU / 8821AU / 8814AU):5b7fc12(8812-dev → 8821-dev at ch36 = 0/7000 on both pre- and post-port — symptom is the known UNII-1 dev-dev gap, not introduced here).DEVOURER_DUMP_CANARY=1confirms all four target registers now match kernel byte-for-byte.🤖 Generated with Claude Code