From 22af43719de48082cdc689eaa9d4d120ae5468c9 Mon Sep 17 00:00:00 2001 From: Simone Date: Fri, 31 Jul 2026 11:25:27 +0200 Subject: [PATCH] docs: the shutdown quiescing plan --- docs/shutdown-quiescing-plan.md | 112 ++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 docs/shutdown-quiescing-plan.md diff --git a/docs/shutdown-quiescing-plan.md b/docs/shutdown-quiescing-plan.md new file mode 100644 index 0000000..1c531a7 --- /dev/null +++ b/docs/shutdown-quiescing-plan.md @@ -0,0 +1,112 @@ +# Piano: quiescing dell'engine a shutdown (`.shutdown`) + +**Contesto** (2026-07-31): ws1-mint ha un hang intermittente di poweroff (LED +acceso, tutto il resto spento), isolato al tratto `machine_power_off()` → +ACPI `_S5`. Evidenza: reboot mai appesi (5/5, anche dopo sessioni di 32 h), +Windows con Fast Startup disattivato mai appeso, journal degli shutdown appesi +byte-identici a quelli puliti, netconsole muto dopo `mlx4_shutdown`. Ipotesi di +lavoro: l'handler SMI del BIOS (ASUS TUF X299 MARK 1, BIOS 4201) al trap di S5 +trova l'engine SMBus dell'iMC in stato "di sessione" e si inchioda. L'engine è +usato tutta la sessione da furyd (ENE 0x27 su entrambi i canali) e dai tool di +sviluppo. + +**Questo piano è hygiene corretta a prescindere dall'esito**: il driver +condivide l'engine con il firmware (vedi commento in testa al sorgente) e oggi +non lo riconsegna mai. La conferma causale resta affidata alla console seriale +(`console=ttyS0`), piano separato. + +Ordine: eseguire prima questo piano, poi il gemello in +`~/_Workspace/furyrs/docs/plans/shutdown-smbus-hygiene.md`. + +--- + +## T1 — Snapshot pristino dei registri a probe + +**GOAL**: salvare, una volta sola al bind, le CMD word di entrambi i canali +com'erano prima di qualunque transfer del driver: sono lo stato che il +firmware ha lasciato al boot e che deve ritrovare a `_S5`. + +**ANCHORS**: `i2c-imc-skylake.c` — `struct imc_smbus` (r. 162), +`imc_pci_probe()` (r. 675, dopo `imc_check_firmware_polling` e prima della +registrazione degli adapter). + +**CHANGE**: due nuovi campi (uno per canale) in `struct imc_smbus`, letti in +probe con l'accessor esistente. Fallimento di lettura (`io_err`) = fallire il +probe: uno snapshot inattendibile rende il quiescing dannoso. + +**CONSTRAINTS**: nessun cambiamento al path dei transfer; niente scritture in +probe. + +**VERIFY**: `grep -n "pristine\|boot_cmd" i2c-imc-skylake.c` mostra campo + +unico punto di scrittura in probe; smoke test invariato. + +## T2 — Callback `.shutdown` + +**GOAL**: a shutdown/kexec: nessun transfer in volo, engine idle, CMD word +pristine ripristinate (mascherate `~GO_BIT`). Best effort, mai bloccante oltre +i timeout esistenti, mai panic. + +**ANCHORS**: `struct pci_driver imc_driver` (r. 770), `imc_suspend()` (r. 637, +modello per marcare gli adapter suspended), `mutex` `s->lock` (r. 165), +`imc_wait_engine_idle()` (r. 218), `imc_restore_xfer()` (r. 366, modello per +la scrittura mascherata). + +**CHANGE**: nuova `imc_pci_shutdown(struct pci_dev *)` registrata in +`imc_driver`. Sequenza-invariante: guard su `drvdata` NULL (probe mai riuscito) +→ marca entrambi gli adapter suspended (blocca nuovi transfer) → `mutex_lock` +(drena l'eventuale transfer in volo, bounded ~750 ms worst case) → attesa +engine idle → ripristino word pristine → unlock. Errori di config space: +ignorati (a shutdown non c'è nessuno a cui riportarli), ma niente scritture se +la lettura dello snapshot in probe era fallita (non accade: T1 fallisce il +probe). + +**CONSTRAINTS**: nessuna allocazione, nessun sleep oltre i poll esistenti; +callback idempotente; vale anche per kexec (stesso callback, stessa +correttezza). + +**VERIFY**: build DKMS pulita per il kernel corrente; +`grep -n "\.shutdown" i2c-imc-skylake.c` → registrata; con `dev_dbg` attivo un +reboot mostra la callback eseguita (`journalctl -k -b -1` dopo reboot con +`dyndbg` sul modulo). + +## T3 — Snapshot rinfrescato al resume + +**GOAL**: dopo S3 il firmware può aver usato l'engine (osservato: read SPD in +memory training al resume) → lo snapshot di probe è potenzialmente stantio. + +**ANCHORS**: `imc_resume()` (r. 648). + +**CHANGE**: se il re-check `imc_check_firmware_polling` passa, ri-leggere le +CMD word e aggiornare lo snapshot prima di rimarcare gli adapter resumed. Se +la lettura fallisce: adapter restano suspended (comportamento attuale sul +fallimento del re-check). + +**VERIFY**: suspend/resume manuale (`test-suspend.sh`) invariato; snapshot +aggiornato osservabile via `dev_dbg`. + +## T4 — Commento di lifetime da correggere + +**GOAL**: il blocco "register state deliberately left as-is on unbind" +(r. 762-769) resta vero per l'unbind a OS vivo ma diventa falso come rationale +globale: a shutdown il prossimo utente è il firmware. + +**CHANGE**: riscrivere il commento distinguendo unbind (as-is, corretto) da +shutdown (handback pristino, T2). È materiale utile anche per il cover letter +v3: engine firmware-shared + caso reale di wedge S5 sotto indagine. + +**VERIFY**: il commento nomina entrambe le semantiche; `checkpatch.pl --strict` +pulito sul diff complessivo. + +## T5 — Versioning + +**CHANGE**: bump `VERSION` e `dkms.conf` (1.0.4); nota in `TODO.md` che il +quiescing è in test come possibile fix dell'hang S5 (link a questo file). + +**VERIFY**: `dkms status` mostra la nuova versione installata per il kernel +corrente; `test-smoke.sh` verde end-to-end. + +--- + +**Fuori scope qui**: qualunque modifica a furyd (piano gemello), la console +seriale, i tool `probe-cf8-*` (restano strumenti di indagine, non li tocca +questo piano).