Strip canaries, double-reads, retries and floors from the module protocol; every bcm method holds the per-module lock for its whole operation; facts stay in docs with internal-client contention marked unresolved

This commit is contained in:
flamingcow
2026-08-13 10:32:24 -07:00
parent 9d1f15045f
commit f2891886f3
3 changed files with 47 additions and 106 deletions
+3 -3
View File
@@ -23,9 +23,9 @@ Protocol and full verified catalog: [bcm84891l-mdio-commands.md](bcm84891l-mdio-
- **SET commands execute stale DATA** — the handler never clears DATA registers; write every parameter register explicitly before any SET.
- **GETs must be invoked bare** — pre-writing *any* DATA register, not just the documented DATA1 display flag, leaves the handler executing as a no-op with results never written (sentinel pre-fills survived GET_SNR untouched, proven on hardware).
- **STATUS must never be written** — any user value (0x0000 and 0x0008 both tried) closes the mailbox: the next command is silently ignored until firmware restores it.
- **PASS cannot prove completion.** The previous command's PASS stays latched while a slow firmware still executes, and until then the DATA registers are firmware scratch — the die temperature turns up in them (0x004E0x0051 observed as "SNR" and "EEE mode"; the campaign's "anomalous 0x0047" was this same race). cabletest reads results twice and requires agreement (DATA1 excluded — temperature lands there autonomously), and discards SNR samples below 15 dB absolute, far under anything a trained link produces and exactly where every garbage signature sits.
- **PASS cannot prove completion.** The previous command's PASS stays latched while a slow firmware still executes, and until then the DATA registers are firmware scratch — the die temperature turns up in them (0x004E0x0051 observed as "SNR" and "EEE mode"; the campaign's "anomalous 0x0047" was this same race).
- **Handler writes during firmware-busy windows wedge the µC permanently** — DATA/CMD writes landing while firmware does post-AN provisioning or training work (a window stretching ~10 s past relink) killed the SMI service four times; reads alone never once. Every handler write — SETs, GET commands, the ECD trigger — runs only in a quiet window: carrier up and stable ≥ 10 s (`phy.go`).
- **Bridge reads carry no fetch identity** — a fetch that outruns the delay leaves the previous transaction's data at 0xAD with no error. cabletest brackets read batches with a known-answer canary (PHY ID 1.2 = 0x3590) and discards the batch on mismatch (`phy.go`).
- **Bridge reads carry no fetch identity** — a fetch that outruns the delay leaves the previous transaction's data at 0xAD with no error.
- Poll STATUS ~100 ms; frozen up to 2 s during 10GBASE-T training — only run after link-up.
## Proven diagnostics
@@ -54,7 +54,7 @@ Protocol and full verified catalog: [bcm84891l-mdio-commands.md](bcm84891l-mdio-
## Firmware-reliability notes
**The firmware is its own mailbox client — the handler is a shared, unarbitrated resource.** Watched read-only on an idle module: CMD sits at 0x0031 (`CMD_GET_CURRENT_TEMP`, bit 15 consumed) and DATA1 tracks the live die temperature (0x4F0x52 ≈ 7982 °C under load), refreshed every ~3.5 s — the firmware issues its own temperature command through the same CMD/STATUS/DATA registers the host uses, with no arbitration. Every mystery this explains: temperature appearing in DATA1 (it is that command's output — the campaign's "anomalous 0x0047" included), PASS satisfying a host poll when it belongs to the internal command, and the µC wedges (two writers colliding on CMD/DATA, likeliest when internal management activity spikes after AN events). Host defenses in `phy.go`: quiet-window writes, double-read results (DATA1 excluded), a CMD readback proving the command was not interleaved, the PHY-ID canary, and the SNR floor. Any GET whose answer lives in DATA1 is unusable; corroborate through IEEE registers or the wire. The hard rule that stands: write every DATA register explicitly before any SET — the handler executes stale DATA.
**The firmware is its own mailbox client — the handler is a shared, unarbitrated resource.** Watched read-only on an idle module: CMD sits at 0x0031 (`CMD_GET_CURRENT_TEMP`, bit 15 consumed) and DATA1 tracks the live die temperature (0x4F0x52 ≈ 7982 °C under load), refreshed every ~3.5 s — the firmware issues its own temperature command through the same CMD/STATUS/DATA registers the host uses, with no arbitration. Every mystery this explains: temperature appearing in DATA1 (it is that command's output — the campaign's "anomalous 0x0047" included), PASS satisfying a host poll when it belongs to the internal command, and the µC wedges (two writers colliding on CMD/DATA, likeliest when internal management activity spikes after AN events). The host side keeps exactly one conversation open at a time (one per-module lock around every whole operation, `phy.go`) and confines writes to quiet windows; **contention with the internal client is otherwise unresolved** — a host GET can still be preempted (~10% per command at the temp cadence) and its results replaced. Any GET whose answer lives in DATA1 is unusable; corroborate through IEEE registers or the wire. The hard rule that stands: write every DATA register explicitly before any SET — the handler executes stale DATA.
## ECD — recovered from the OpenBCM SDK, proven on hardware