From 9e95e4eb8504f037c48d69712d1198884cd5edcc Mon Sep 17 00:00:00 2001 From: Joseph <162703152+josephnef@users.noreply.github.com> Date: Mon, 20 Jul 2026 20:29:16 +0300 Subject: [PATCH] Jaguar2: extend the firmware channel-switch fast path to the 8821C MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The fw fast path (H2C 0x1D SINGLE_CHANNELSWITCH_V2) was gated to ChipVariant::C8822B, but the whole path is variant-generic — the HMEBOX H2C submit and the RF18 low-byte channel confirm are identical on both Jaguar2 dies, and the vendor 8821C firmware carries the same rtw_ch_switch_offload. Drop the variant restriction so DEVOURER_FASTRETUNE_FW covers both 8822B and 8821C. Also validates the 8822E on-air (an RTL8822EU was on the rig, previously mislabelled): 36<->40 fw 1.92 ms median dead air (n=797, p99 5.16), in line with the 8822C. Coverage now: fw fast path on all four Jaguar2/3 dies; on-air-validated on 8822B, 8822C, 8822E; 8821C code-covered pending a hardware pass (no 8821C part on the rig). Docs + config knob + CLAUDE.md updated to state the per-die coverage. Co-Authored-By: Claude Opus 4.8 --- CLAUDE.md | 10 +++++----- docs/frequency-hopping.md | 4 ++-- docs/kernel-channel-switch-offload.md | 21 +++++++++++++++------ src/DeviceConfig.h | 4 ++-- src/jaguar2/CLAUDE.md | 6 ++++-- src/jaguar2/HalJaguar2.cpp | 16 ++++++++++------ 6 files changed, 38 insertions(+), 23 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 73dadb5..5dd8dbe 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -317,11 +317,11 @@ temporal layer and injects each at its ladder's rate `IRtlDevice::FastRetune(channel)` — lean intra-band, same-bandwidth retune on every generation (RF channel switch only, write-only from a compose cache); falls back to full `SetMonitorChannel` on a band change. FHSS-grade: ~0.5–2.5 ms -per hop depending on chip. On the 8822B and 8822C/8822E, -`DEVOURER_FASTRETUNE_FW=1` hands the hop to the chip firmware instead (H2C -0x1D, fire-and-confirm-later): ~1.4 ms dead air on the 8822B (a tie on-air on -the 8822C, but ~3× cheaper host-side), and `=2` extends it to **cross-band** -hops (~2–2.6 ms vs the ~90 ms full path) — protocol + bench: +per hop depending on chip. On the Jaguar2 dies (8822B, 8821C) and Jaguar3 +(8822C, 8822E), `DEVOURER_FASTRETUNE_FW=1` hands the hop to the chip firmware +instead (H2C 0x1D, fire-and-confirm-later): ~1.4 ms dead air on the 8822B (a +tie on-air on the 8822C/8822E, but ~3× cheaper host-side), and `=2` extends it +to **cross-band** hops (~2–2.6 ms vs the ~90 ms full path) — protocol + bench: `docs/kernel-channel-switch-offload.md`. `send_packet` honours a radiotap `CHANNEL` field, so hopping is per-packet and radiotap-driven like rate. Demos hop via `DEVOURER_HOP_CHANNELS` (SweepSpec grammar: `1,6,11`, `36-48/4`, `5170-5250/5` diff --git a/docs/frequency-hopping.md b/docs/frequency-hopping.md index 5bb8e8b..5ffa2c2 100644 --- a/docs/frequency-hopping.md +++ b/docs/frequency-hopping.md @@ -333,9 +333,9 @@ every generation overrides it with a lean path built from the tricks above: |-----|-----------|---------------|----------------------|-------------|--------------| | RTL8812AU (Jaguar1) | ~277 ms | **~1.6 ms** | — | ~0.8 ms | 2 | | RTL8822BU (Jaguar2) | ~65 ms | **~2.5 ms** | ~2.6 ms | ~1.0 ms | 2 | -| RTL8821CU (Jaguar2) | ~30 ms | **~0.55 ms** | — | ~0.5 ms | 1 | +| RTL8821CU (Jaguar2) | ~30 ms | **~0.55 ms** | code-covered, no HW | ~0.5 ms | 1 | | RTL8822CU (Jaguar3) | ~12 ms | **~1.9 ms** | **~0.8 ms** | ~0.21 ms | 9 | -| RTL8812EU (Jaguar3) | ~12 ms | **~2.4 ms** | (same path, unvalidated) | ~0.27 ms | 9 | +| RTL8812EU (Jaguar3) | ~12 ms | **~2.4 ms** | **~0.8 ms** (8822E) | ~0.27 ms | 9 | (Median `hop.dwell` switch_us over a 1/6/11 hop set; per-stage numbers from `DEVOURER_HOP_PROF=1`. Every hop microsecond is USB round-trips: one register diff --git a/docs/kernel-channel-switch-offload.md b/docs/kernel-channel-switch-offload.md index 9a6796d..14b6540 100644 --- a/docs/kernel-channel-switch-offload.md +++ b/docs/kernel-channel-switch-offload.md @@ -105,9 +105,9 @@ Reading: ## The devourer port (`DEVOURER_FASTRETUNE_FW`) -Devourer ships the offload as a `FastRetune` fast path -(`HalJaguar2::fw_channel_switch` on the 8822B; -`RadioManagementJaguar3::fast_retune`'s fw block on the 8822C/8822E): the +Devourer ships the offload as a `FastRetune` fast path across both Jaguar2 +dies (`HalJaguar2::fw_channel_switch`) and both Jaguar3 dies +(`RadioManagementJaguar3::fast_retune`'s fw block): the H2C rides the classic HMEBOX mailboxes devourer already drives, and completion is **fire-and-confirm-later** — polling RF18 during the switch measurably @@ -144,9 +144,18 @@ because the 8822C's RF settle dominates its dark time whichever engine sequences it; the fw win there is the per-hop host cost (~0.6 ms H2C submit vs ~1.9 ms of composed USB writes). Cross-band 36↔6 through the firmware: **2.63 ms median** (n=379, p99 11.0) versus the ~90 ms full -path. Hopping-RX decode identical fw vs sw. The 8822E shares the code -path (not yet on-air-validated — no E-die on the rig this session); its -spur channels conservatively decline the fast path, fw included. +path. Hopping-RX decode identical fw vs sw. The 8822E (RTL8822EU) runs the +same code path and is on-air-validated too: 36↔40 fw **1.92 ms median** +(n=797, p99 5.16), in line with the 8822C; its spur channels +conservatively decline the fast path, fw included. + +**Chip coverage.** The fw fast path covers both Jaguar2 dies (8822B, 8821C) +and both Jaguar3 dies (8822C, 8822E). On-air-validated: 8822B, 8822C, +8822E. The 8821C shares the variant-generic H2C submit and RF18-channel +confirm and the vendor 8821C firmware carries the same +`SINGLE_CHANNELSWITCH_V2` offload, but no 8821C part was on the rig, so its +fw path is code-covered pending a hardware pass. Jaguar1 has no such +firmware switch; Kestrel (rtw89) is a separate architecture. ## Go/no-go for the series diff --git a/src/DeviceConfig.h b/src/DeviceConfig.h index 0b5d537..e1c03c0 100644 --- a/src/DeviceConfig.h +++ b/src/DeviceConfig.h @@ -218,8 +218,8 @@ struct DeviceConfig { bool thermal_track = true; /* env: DEVOURER_FASTRETUNE_FW — FastRetune firmware fast path (H2C 0x1D * SINGLE_CHANNELSWITCH_V2, the switch the vendor drivers gate behind - * rtw_ch_switch_offload) on the 8822B (Jaguar2) and 8822C/8822E - * (Jaguar3): 0 = off (software compose path), 1 = firmware switch for + * rtw_ch_switch_offload) on the Jaguar2 dies (8822B, 8821C) and the + * Jaguar3 dies (8822C, 8822E): 0 = off (software compose path), 1 = firmware switch for * intra-band 20/40 MHz hops, 2 = additionally accept cross-band hops * (the firmware reprograms the band block; TXAGC baseline stays the * bring-up band's — active power knobs re-fold). Bench + protocol: diff --git a/src/jaguar2/CLAUDE.md b/src/jaguar2/CLAUDE.md index 1439b1c..939eb72 100644 --- a/src/jaguar2/CLAUDE.md +++ b/src/jaguar2/CLAUDE.md @@ -34,8 +34,10 @@ Jaguar1 (shared `PhyTableLoader`). RF18-edge bug. - The TXAGC block is write-only, so `GetTxPowerState` reports the software shadow (`hw_readback=false`). -- **8822B firmware channel switch** (H2C 0x1D `SINGLE_CHANNELSWITCH_V2`, - `fw_channel_switch` + the `fastretune_fw` knob): the fw executes the whole +- **Firmware channel switch** (H2C 0x1D `SINGLE_CHANNELSWITCH_V2`, + `fw_channel_switch` + the `fastretune_fw` knob; both Jaguar2 dies — the + path is variant-generic, 8822B on-air-validated, 8821C code-covered + pending hardware): the fw executes the whole retune in ~1–2 ms and reports C2H `CUR_CHANNEL`. Never poll RF18 *during* the switch — the PI reads contend with the firmware's RF-bus writes and triple the on-air dark time; confirm the previous switch at the next hop diff --git a/src/jaguar2/HalJaguar2.cpp b/src/jaguar2/HalJaguar2.cpp index 78ee080..7d7df39 100644 --- a/src/jaguar2/HalJaguar2.cpp +++ b/src/jaguar2/HalJaguar2.cpp @@ -1336,12 +1336,16 @@ bool HalJaguar2::fast_retune(uint8_t channel, uint8_t bw, return true; /* no-op hop */ /* Firmware fast path (DEVOURER_FASTRETUNE_FW): hand the whole retune to - * the 8822B firmware via H2C 0x1D instead of the composed register - * sequence below. Mode 2 additionally accepts band changes — the firmware - * reprograms the band block itself (bench-measured ~2 ms cross-band, - * docs/kernel-channel-switch-offload.md) — which the software path cannot. - * 20/40 MHz only (the 80 MHz primary-idx pairing stays on the sw path). */ - if (_cfg.tuning.fastretune_fw > 0 && _variant == ChipVariant::C8822B && + * the firmware via H2C 0x1D instead of the composed register sequence + * below. Both Jaguar2 dies expose it — the H2C submit (HMEBOX) and the + * RF18-channel confirm are variant-generic, and the vendor 8821C firmware + * carries the same SINGLE_CHANNELSWITCH_V2 offload as the 8822B's + * (on-air-validated) one. Mode 2 additionally accepts band changes — the + * firmware reprograms the band block itself (bench-measured ~2 ms + * cross-band, docs/kernel-channel-switch-offload.md) — which the software + * path cannot. 20/40 MHz only (the 80 MHz primary-idx pairing stays on the + * sw path). */ + if (_cfg.tuning.fastretune_fw > 0 && (!band_change || _cfg.tuning.fastretune_fw >= 2) && (bw == 0 /*20*/ || bw == 1 /*40*/)) { devourer::HopProf prof(_logger->events(), _cfg.debug.hop_prof, "j2fw",