Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ construction from the `SYS_CFG2` chip-id (Kestrel: PID-first):
and rtl8822e (RTL8812EU/8822EU, chip-id `0x17`). 5/10 MHz narrowband,
80 MHz (incl. a 40-in-80 frame), halrf calibration. Sustained 5 GHz TX
needs the coex runtime thread (started in `InitWrite`) — without it the
combo chip's coex firmware silences the antenna. 8822e constraints:
combo chip's coex firmware silences the antenna. A host that owns bulk-IN
itself can opt out (`tuning.j3_runtime_thread`, see `src/jaguar3/CLAUDE.md`
for what that costs). 8822e constraints:
`docs/8822e-quirks.md`.
- **Kestrel** (`src/kestrel/`): the Wi-Fi 6 / 802.11ax generation —
RTL8852BU/8832BU (variant C8852B) and RTL8852CU/8832CU (C8852C), one HAL
Expand Down
2 changes: 2 additions & 0 deletions examples/common/env_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,8 @@ devourer::DeviceConfig devourer_config_from_env() {
cfg.tuning.skip_trx_reassert = env_flag("DEVOURER_SKIP_TRX_REASSERT");
cfg.tuning.skip_rfe_init = env_flag("DEVOURER_SKIP_RFEINIT");
cfg.tuning.skip_coex = env_flag("DEVOURER_SKIP_COEX");
if (const char *e = env_str("DEVOURER_J3_RUNTIME"))
cfg.tuning.j3_runtime_thread = std::strcmp(e, "0") != 0;
cfg.tuning.skip_dig = env_flag("DEVOURER_SKIP_DIG");
/* Default-on knob: unset = tracking on; only "0" disables it. */
if (const char *e = env_str("DEVOURER_THERMAL_TRACK"))
Expand Down
23 changes: 22 additions & 1 deletion src/DeviceConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,28 @@ struct DeviceConfig {
bool skip_trx_reassert = false; /* env: DEVOURER_SKIP_TRX_REASSERT (J2) */
bool skip_rfe_init = false; /* env: DEVOURER_SKIP_RFEINIT (J2) */
bool skip_coex = false; /* env: DEVOURER_SKIP_COEX (J2) */
bool skip_dig = false; /* env: DEVOURER_SKIP_DIG (J2) */
/* env: DEVOURER_J3_RUNTIME ("0" disables) — Jaguar3: start the coex /
* phydm watchdog runtime thread after bring-up (default ON). With no RX
* loop running, that thread also keeps a bulk-IN read posted to drain
* firmware C2H reports, and every ~2 s it writes coex, TX-power tracking
* and DIG/EDCCA registers. A host that owns bulk-IN itself (raw C2H)
* turns it off. This flag covers only that post-bring-up thread:
* StartRxLoop still runs its own phydm watchdog (DIG included) when the
* thread is off, so fixed gain during an RX session also needs skip_dig.
* A TX-only session with the thread off loses all of it: nothing drains
* C2H, so no tx.report (CCX) is emitted; pwr_track (thermal TX-power
* compensation, which sustains upper 5 GHz) stops; and the coex re-apply
* and FW heartbeats stop (src/jaguar3/CLAUDE.md: sustained 5 GHz TX
* needs them). */
bool j3_runtime_thread = true;
/* env: DEVOURER_SKIP_DIG — J2: StartRxLoop starts no DIG thread; J3: the
* phydm watchdog (runtime thread and StartRxLoop worker) skips its DIG
* step.
* On J3 the wide-TX IGI floor (wide_tx_igi_floor) still writes IGI: the
* first 40/80 MHz frame raises a lower IGI to the floor, and leaving the
* floor clamps IGI down to the DIG window top. For IGI that stays exactly
* where the host put it, also set DEVOURER_WIDE_TX_IGI_FLOOR=0. */
bool skip_dig = false;
/* env: DEVOURER_THERMAL_TRACK — Jaguar2 thermal TX-power tracking
* (default ON; "0" disables). A ~2 s tick reads the RF 0x42 thermal
* meter, computes the delta vs the efuse baseline, and writes the vendor
Expand Down
3 changes: 3 additions & 0 deletions src/jaguar3/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ narrowband dividers, RF18 encoding), strategy interfaces `Jaguar3Calibration`
`InitWrite`): sustained 5 GHz TX needs it — without its ~2 s WiFi-only coex
re-apply + FW heartbeats, the combo chip's coex firmware silences the
antenna. It also drains C2H, so TX-only sessions still see `tx.report`.
Opt-out: `tuning.j3_runtime_thread = false` (`DEVOURER_J3_RUNTIME=0`), for
a host that owns bulk-IN itself. A TX-only session then gets no
`tx.report`, no `pwr_track` and no coex/FW heartbeats.
- **5/10 MHz narrowband**: the re-clock lives in the `0x9b0`/`0x9b4`
dividers (vs the `0x8ac` block the Jaguar1/2 chips share). 80 MHz works,
incl. a 40-in-80 frame via TX-descriptor DATA_SC. See `docs/narrowband.md`.
Expand Down
5 changes: 3 additions & 2 deletions src/jaguar3/PhydmRuntimeJaguar3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,9 +226,10 @@ void PhydmRuntimeJaguar3::edcca(uint8_t igi) {
}
}

void PhydmRuntimeJaguar3::tick(uint8_t channel, bool edcca_track) {
void PhydmRuntimeJaguar3::tick(uint8_t channel, bool edcca_track, bool dig_track) {
const FaStats fa = fa_statistics_and_reset();
dig(fa, is_dfs_channel(channel));
if (dig_track)
dig(fa, is_dfs_channel(channel));
if (fa.cck_enabled)
cck_pd(fa);
if (edcca_track)
Expand Down
6 changes: 4 additions & 2 deletions src/jaguar3/PhydmRuntimeJaguar3.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@ class PhydmRuntimeJaguar3 {
/* One watchdog pass: FA/CCA statistics + reset, DIG, CCK-PD (2 GHz),
* EDCCA. `channel` = current center channel (band + DFS decision),
* `edcca_track` = false leaves 0x84c untouched (DEVOURER_DIS_CCA /
* SetCcaMode owns the thresholds then). */
void tick(uint8_t channel, bool edcca_track);
* SetCcaMode owns the thresholds then); `dig_track` = false skips DIG
* (DEVOURER_SKIP_DIG; the wide-TX IGI floor still applies, see
* set_igi_floor). */
void tick(uint8_t channel, bool edcca_track, bool dig_track);

/* A channel/bandwidth change invalidates the CCK-PD applied-level cache
* (the kernel re-checks bw/nrx from registers each apply; the level is
Expand Down
9 changes: 6 additions & 3 deletions src/jaguar3/RtlJaguar3Device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ void RtlJaguar3Device::StartRxLoop(Action_ParsedRadioPacket packetProcessor) {
std::lock_guard<std::mutex> lk(_reg_mu);
/* edcca_track follows the EDCCA gate alone — see the housekeeping
* tick below for why the all-or-nothing flag is the wrong input. */
_phydm.tick(_channel.Channel, !_cca_edcca_disabled);
_phydm.tick(_channel.Channel, !_cca_edcca_disabled, !_cfg.tuning.skip_dig);
} catch (...) {
break; /* chip gone — the RX loop will wind down too */
}
Expand Down Expand Up @@ -578,7 +578,7 @@ void RtlJaguar3Device::coex_runtime_loop() {
* thresholds at 0x84c every ~2 s in the EDCCA-off/primary-on arm,
* undoing the disable the caller asked for. Jaguar1 does the same
* thing via SetEdccaTrack(!edcca_disabled) at the end of apply_cca. */
_phydm.tick(_channel.Channel, !_cca_edcca_disabled);
_phydm.tick(_channel.Channel, !_cca_edcca_disabled, !_cfg.tuning.skip_dig);
_hal.fw_update_wl_phy_info();
_hal.fw_set_pwr_mode_active();
_hal.fw_coex_query_bt_info();
Expand Down Expand Up @@ -1177,7 +1177,10 @@ void RtlJaguar3Device::InitWrite(SelectedChannel channel) {
* adapter's transfer counter, so anything emitted after it would count
* that thread's register and H2C traffic as bring-up. */
timer.total();
_coex_thread = std::thread([this] { coex_runtime_loop(); });
if (_cfg.tuning.j3_runtime_thread)
_coex_thread = std::thread([this] { coex_runtime_loop(); });
Comment thread
snokvist marked this conversation as resolved.
else
_logger->info("Jaguar3: coex/phydm runtime thread not started (tuning.j3_runtime_thread)");
if (_cfg.rx.ack_responder &&
!SetAckResponder(*_cfg.rx.ack_responder)) /* DEVOURER_ACK_RESPONDER */
throw std::runtime_error(
Expand Down
Loading