Adapter doctor — dying-dongle triage (EFUSE stability / fw-boot / RX smoke)#211
Merged
Conversation
…smoke) A dying adapter can enumerate cleanly, init green, and still be stone-deaf: the #205 unit's EFUSE reads return stochastic garbage (wrong RFE/PA/LNA -> wrong PHY tables) and its 8051 never boots firmware — non-fatal on Jaguar1, so nothing aborts. No "did init succeed" check reaches either. This adds the probes and a triage tool so both the bench and end users can grade a suspect dongle. Library (all generations): - src/AdapterHealth.h — EfuseStability / FwBootStatus structs, the shared physical-map cross-compare loop, and a pure classifier (HEALTHY / SUSPECT / FAILING + reason bits), ctest'd in tests/adapter_health_selftest.cpp with cases encoding the verdicts measured on the real dying unit vs its healthy twin. - IRtlDevice::ProbeEfuseStability(N) — N fresh PHYSICAL EFUSE map reads cross-compared byte-for-byte + 0x8129 ID validation. Healthy silicon is byte-identical every read; any mismatch is conclusive. Wired per generation: J1 via EepromManager::ReadPhysicalEfuseMap, J2 via the public logical-map reader, J3 8822C only — the 8822E's OTP is not reliably readable post-bring-up by design (see cache_efuse_8822e), so probing it would flag healthy units. - IRtlDevice::GetFwBootStatus — the fw-download outcome recorded at the real hardware boundaries in each generation's DLFW machine: checksum_ok = IMEM/DMEM checksum-ready (MCUFW_CTRL & 0x50 on J2/J3, chksum report on J1), ready_ok = the boot handshake (0xC078 / CPU_DL_READY). Distinguishes a transport failure from a downloaded-but-never-booted MCU, and survives the fatal bring-up throw on J2/J3 so an init abort still says which stage died. Tool + harness: - examples/doctor — pure-CLI triage: bring-up, EFUSE probe, fw status, RX smoke (deaf = FAILING only with --expect-traffic, else SUSPECT — RF-quiet rooms lie). Verdict in the exit code (0/1/2), <devourer-doctor> machine line, --vid/--bus/--port topology select for same-PID/same-serial rigs. - tests/adapter_doctor_cold.sh — definitive-verdict wrapper: per-rep VBUS cold on uhubctl-switchable hub ports, in-tree rtw88 module temp-blacklisted (udev reloads it on every re-enumeration), radiation-verified beacon flood. DOCTOR_SKIP_VBUS=1 for DUTs on root ports (never uhubctl root ports on this rig). - docs/adapter-doctor.md + README/CLAUDE.md pointers. Hardware-validated on the bench: dying 8812AU FAILING 2/2 from true cold (fw-dead + deaf-to-flood — its EFUSE happened to read stable that session; the sickness drifts, which is why independent probes), healthy 8812AU / 8821CU HEALTHY 2/2 from true cold, 8822BU (T3U) HEALTHY 2/2, 8812CU HEALTHY, 8812EU HEALTHY with the probe correctly refused. 11/11 ctest; jaguar1-only and jaguar2-only subset builds green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The mingw job builds an explicit target list and its Test step fails any registered ctest binary that isn't in it as Not Run — which is exactly what adapter_health_classify did on the first push. Co-Authored-By: Claude Opus 4.8 <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.
Follow-up to #205. That investigation ended with a dongle that enumerates cleanly, inits green, and is stone-deaf — its EFUSE reads return stochastic garbage (wrong RFE/PA/LNA → wrong PHY tables) and its 8051 never boots firmware (deliberately non-fatal on Jaguar1). Neither is visible to any "did init succeed" check, on the bench or in the field. This PR makes both measurable and ships a triage tool.
Library — health probes on
IRtlDevice(all generations)ProbeEfuseStability(N)— N fresh physical EFUSE logical-map reads (not the cached shadow), cross-compared byte-for-byte +0x8129EEPROM-ID validation. Healthy silicon is byte-identical on every read, cold or warm — any mismatch is conclusive dying-silicon evidence. Wired per generation: J1 (EepromManager::ReadPhysicalEfuseMap), J2 (public logical-map reader), J3 8822C only — the 8822E's OTP is not reliably readable post-bring-up by design (seecache_efuse_8822e), so probing it would false-flag healthy units; it reportssupported=false.GetFwBootStatus()— the firmware-download outcome recorded at the real hardware boundaries inside each generation's DLFW machine:checksum_ok= IMEM/DMEM checksum-ready (MCUFW_CTRL & 0x50on J2/J3, the chksum report on J1),ready_ok= the boot handshake (0xC078/ CPU_DL_READY). Distinguishes a transport/checksum failure from a downloaded-but-never-booted MCU — and survives the fatal bring-up throw on J2/J3, so an init abort still reports which stage died.src/AdapterHealth.h— structs, the shared probe loop, and a pure classifier (HEALTHY / SUSPECT / FAILING+ reason bits). Grading rules documented next to the code;ctest'd (adapter_health_classify) with cases encoding the verdicts measured on the real dying unit vs its healthy twin — including the edges (blank dev-board EFUSE, RF-quiet silence, corrupt-frame ratios deliberately ungraded).Tool + harness
examples/doctor— pure-CLI end-user triage: bring-up → EFUSE probe → FW status → RX smoke. Deaf grades FAILING only when--expect-trafficvouches for a source (an RF-quiet room is otherwise indistinguishable); verdict in the exit code (0/1/2),<devourer-doctor>machine line,--vid/--bus/--porttopology select for rigs with same-PID/same-serial adapters.tests/adapter_doctor_cold.sh— definitive-verdict wrapper: per-rep VBUS cold via uhubctl, in-tree rtw88 module temp-blacklisted (udev modalias reloads it at every re-enumeration — a baremodprobe -rdoes not survive), radiation-verified canonical-SA flood.DOCTOR_SKIP_VBUS=1for DUTs on root ports.docs/adapter-doctor.md+ README/CLAUDE.md pointers.Hardware validation
The dying unit's EFUSE happened to read stable during the validation session — its sickness drifts between faces (garbage EFUSE / valid-ID-with-dead-MCU / deaf RX), which is exactly why the doctor probes independent subsystems: the verdict landed anyway, via the FW and vouched-deaf checks. A cheap external cross-check is also documented: the in-tree rtw88 probe fails
failed to validate firmwareon such a unit and binds cleanly on a healthy one.11/11
ctest;jaguar1-onlyandjaguar2-onlysubset builds verified green (all probe wiring lives inside each generation's own conditionally-compiled directory — no new#ifguards needed).🤖 Generated with Claude Code