Files
i2c-imc-skylake/tools/pre-poweroff-load.sh
T
Simone d1b48b2b16 tools: fixed SMBus load protocol for the poweroff-hang observation window
pre-poweroff-load.sh runs the same mixed, deterministic workload before
every poweroff, so each observation carries identical bus exposure in both
the use_ecam=1 phase and the use_ecam=0 counter-proof. It records one line
per run (use_ecam, srcversion, blocks, warns, spd_ok) and keeps the full
per-run output beside it, then powers the machine off by itself.

Two runs of 2026-08-09 are included: without them the log is a claim.
2026-08-14 17:49:56 +02:00

155 lines
5.2 KiB
Bash
Executable File

#!/bin/bash
# pre-poweroff-load.sh - fixed SMBus load protocol for the A5 hang observation
# window (TODO.md E1), fully automatic: runs the load, saves observations,
# powers the machine off.
#
# Mixed, deterministic workload so that every poweroff in the window carries
# the same, high and *diverse* bus exposure - both in the use_ecam=1 phase and
# in the use_ecam=0 counter-proof phase. Each 3-minute block:
#
# 1. software effect (~2760 SMBus writes/s, steady stream) ~100 s
# 2. rapid hw/sw switch burst (6 alternations back-to-back:
# one-shot config-write bursts + apply latches) ~20 s
# 3. hardware effect (engine-side, bus quiet) ~30 s
# 4. full SPD dump of all 4 DIMMs via ee1004 (reads +
# page-selects) + serial integrity check ~30 s
#
# Effects rotate through fixed lists, so run N of phase A and run N of phase B
# execute the identical sequence.
#
# End of run: kernel-journal warnings and run context are saved to a per-run
# file in tools/pre-poweroff-runs/, one summary line is appended to
# pre-poweroff-load.log, and - only with --poweroff - the machine POWERS OFF
# (15 s grace, Ctrl-C to abort). The last software effect is left running into
# the poweroff on purpose: exposure should cover the shutdown path too; the
# systemd boot scene restores the normal LED state at next boot.
#
# The one exception: an SPD serial mismatch saves everything and does NOT
# power off - investigate before shutting down.
#
# Usage: sudo ./pre-poweroff-load.sh [minutes] [--poweroff]
# (default 30 minutes, in 3-min blocks; re-execs itself under sudo if
# started as a plain user; powers off at the end ONLY with --poweroff)
set -eu
[ "$(id -u)" -eq 0 ] || exec sudo "$0" "$@"
MINUTES=30
POWEROFF=0
for arg in "$@"; do
case "$arg" in
--poweroff) POWEROFF=1 ;;
*) MINUTES="$arg" ;;
esac
done
BLOCKS=$(((MINUTES + 2) / 3))
DIR="$(cd "$(dirname "$0")" && pwd)"
LOG="$DIR/pre-poweroff-load.log"
RUNDIR="$DIR/pre-poweroff-runs"
START="$(date '+%Y-%m-%d %H:%M:%S')"
RUNFILE="$RUNDIR/$(date '+%Y%m%d-%H%M').log"
ANIMS=(aurora wave_rainbow plasma ripple gradient_pulse fire)
FX=(respiro arcobaleno cometa battito ciclico lampeggio)
# SPD EEPROMs at 0x50/0x52 (ee1004); i2c bus numbers depend on module load
# order, so discover them instead of hardcoding bus IDs.
mapfile -t EEPROMS < <(ls /sys/bus/i2c/devices/*-005[02]/eeprom 2>/dev/null | sort)
[ "${#EEPROMS[@]}" -eq 4 ] || { echo "ERROR: expected 4 SPD EEPROMs, found ${#EEPROMS[@]}"; exit 1; }
MODE="$(cat /sys/module/i2c_imc_skylake/parameters/use_ecam 2>/dev/null || echo '?')"
SRCV="$(cat /sys/module/i2c_imc_skylake/srcversion 2>/dev/null || echo '?')"
mkdir -p "$RUNDIR"
spd_serials() {
local e
for e in "${EEPROMS[@]}"; do
dd if="$e" bs=1 skip=325 count=4 2>/dev/null | xxd -p
done
}
echo "== pre-poweroff load: ${BLOCKS} blocks (~$((BLOCKS * 3)) min), use_ecam=${MODE}, srcversion=${SRCV}"
if [ "$POWEROFF" -eq 1 ]; then
echo "== POWERS OFF at the end. Run file: ${RUNFILE}"
else
echo "== no poweroff at the end (use --poweroff). Run file: ${RUNFILE}"
fi
REF_SERIALS="$(spd_serials)"
echo "== SPD serial reference: $(echo "$REF_SERIALS" | tr '\n' ' ')"
SPD_BAD=0
for ((b = 0; b < BLOCKS; b++)); do
anim="${ANIMS[b % ${#ANIMS[@]}]}"
fx="${FX[b % ${#FX[@]}]}"
echo "-- block $((b + 1))/${BLOCKS}: anim=${anim} fx=${fx}"
furyrs anim "$anim"
sleep 100
# rapid hw/sw alternation burst
for ((i = 0; i < 3; i++)); do
furyrs effect "${FX[(b + i) % ${#FX[@]}]}"
sleep 2
furyrs anim "${ANIMS[(b + i) % ${#ANIMS[@]}]}"
sleep 2
done
furyrs effect "$fx"
sleep 30
# full SPD dump (reads + ee1004 page-selects) + integrity check
for e in "${EEPROMS[@]}"; do
dd if="$e" bs=64 2>/dev/null >/dev/null
done
if [ "$(spd_serials)" != "$REF_SERIALS" ]; then
SPD_BAD=1
echo "!! SPD SERIAL MISMATCH in block $((b + 1)) - stopping, will NOT power off"
break
fi
done
# leave a steady software effect running into the poweroff
furyrs anim "${ANIMS[0]}"
# Only warning-and-up: the dev_dbg per-transfer traffic is not an anomaly.
WARNS="$(journalctl -k -p warning --since "$START" --no-pager 2>/dev/null | grep -i 'i2c-imc' || true)"
N="$(printf '%s' "$WARNS" | grep -c . || true)"
{
echo "start: ${START}"
echo "end: $(date '+%Y-%m-%d %H:%M:%S')"
echo "use_ecam: ${MODE}"
echo "srcversion: ${SRCV}"
echo "blocks: ${BLOCKS}"
echo "spd_ok: $((1 - SPD_BAD))"
echo "spd_serials_ref:"
echo "$REF_SERIALS"
echo "driver_warnings: ${N}"
[ "$N" -gt 0 ] && echo "$WARNS"
} >"$RUNFILE"
echo "$(date '+%Y-%m-%d %H:%M') use_ecam=${MODE} srcversion=${SRCV} blocks=${BLOCKS} warns=${N} spd_ok=$((1 - SPD_BAD))" >>"$LOG"
[ -n "${SUDO_UID:-}" ] && chown "$SUDO_UID:${SUDO_GID:-$SUDO_UID}" "$RUNFILE" "$LOG" "$RUNDIR"
sync
if [ "$SPD_BAD" -ne 0 ]; then
echo "== SPD integrity FAILED - observations in ${RUNFILE} - NOT powering off."
exit 1
fi
if [ "$N" -gt 0 ]; then
echo "== ${N} driver warning(s) - SIGNAL, saved in ${RUNFILE}:"
echo "$WARNS"
else
echo "== clean run, no driver warnings."
fi
if [ "$POWEROFF" -eq 1 ]; then
echo "== powering off in 15 s (Ctrl-C to abort) ..."
sleep 15
systemctl poweroff
else
echo "== done, NOT powering off (pass --poweroff to shut down at the end)."
fi