Name card folders by GPU UUID, record serial in serial.txt

Folder identity switches from the physical serial (which neither
nvflash nor nvidia-smi exposes on the 170HX) to the auto-read GPU
UUID from nvidia-smi. The physical serial probe result (or N/A) is
saved to <folder>/serial.txt and report.json. No manual serial
prompt anymore; --serial only overrides the recorded serial.
Unidentified runs fall back to unidentified/<bdf>/. AGENTS.md
invariant and README updated to match.
This commit is contained in:
2026-10-15 00:17:13 +02:00
parent 70a6ff9b1a
commit ac53b83f70
4 changed files with 50 additions and 27 deletions
+25 -13
View File
@@ -1,13 +1,13 @@
#!/usr/bin/env python3
"""CMP 170HX single-card checker - ONE card per run, no queue.
Per run: wait for card -> auto serial -> VBIOS backup -> PCIe link/AER/config
checks -> retrain + rescan tests -> dmesg scrape -> cmpunlocker verify.sh
(read-only) -> opt-in cmpunlocker unlock (install.sh, y/N or --unlock; a
successful install skips VRAM stress and asks for a cold reboot, then you
re-run this script for the final Gen2 x16 PCIe check)
Per run: wait for card -> auto UUID (folder) + serial probe -> VBIOS backup
-> PCIe link/AER/config checks -> retrain + rescan tests -> dmesg scrape
-> cmpunlocker verify.sh (read-only) -> opt-in cmpunlocker unlock (install.sh,
y/N or --unlock; a successful install skips VRAM stress and asks for a cold
reboot, then you re-run this script for the final Gen2 x16 PCIe check)
-> optional 5-min Vulkan VRAM stress (last step, ask yes/no)
-> cards/<serial>/report.json.
-> cards/<GPU-UUID>/report.json (+ serial.txt with the physical serial or N/A).
Scoring: FAIL on no-device/link-down/lost-after-rescan, and on a final
post-unlock link other than Gen2 x16; WARN on correctable AER/Xid/width< x16/
@@ -121,12 +121,19 @@ def process_card(args):
ok(f"device found at {bdf} ({devid})")
nf = X.nvflash_bin(args)
serial, serial_src = X.get_serial(nf, args)
folder = X.CARDS_DIR / sanitize(serial)
uuid = X.get_gpu_uuid()
if uuid:
folder = X.CARDS_DIR / sanitize(uuid)
else:
warn("GPU UUID unavailable - filing run under unidentified/")
folder = X.UNIDENTIFIED_DIR / sanitize(bdf)
folder.mkdir(parents=True, exist_ok=True)
serial, serial_src = X.get_serial(nf, args)
(folder / "serial.txt").write_text((serial or "N/A") + "\n")
info(f"folder: {folder}")
rep = {
"uuid": uuid, "folder": str(folder),
"serial": serial, "serial_source": serial_src, "started_at": now_iso(),
"bdf": bdf, "device_id": devid, "host": X.run(["uname", "-n"])["out"].strip(),
"kernel": X.run(["uname", "-r"])["out"].strip(),
@@ -220,12 +227,13 @@ def process_card(args):
(folder / "report.json").write_text(json.dumps(rep, indent=2))
print()
label = rep.get("uuid") or folder.name
if result == "PASS":
ok(f"{serial}: PASS")
ok(f"{label}: PASS")
elif result == "WARN":
warn(f"{serial}: WARN")
warn(f"{label}: WARN")
else:
err(f"{serial}: FAIL")
err(f"{label}: FAIL")
for f in fails:
err(" FAIL: " + f)
for w in warns:
@@ -237,7 +245,7 @@ def process_card(args):
# ---------------------------------------------------------------- demo
def demo(args):
"""Validate report pipeline without hardware: writes cards/DEMO-*."""
"""Validate report pipeline without hardware: writes cards/GPU-DEMO-UUID-0001."""
step("Demo mode (no hardware)")
args.vulkan = "never"
args.serial = "DEMO-SERIAL-001"
@@ -245,12 +253,14 @@ def demo(args):
orig_wait = globals()["wait_for_gpu"]
orig_detect, orig_check = X.detect_gpus, X.check_link
orig_uuid = X.get_gpu_uuid
orig_aer, orig_dm, orig_cfg = X.aer_snapshot, X.dmesg_capture, X.dump_config
orig_retrain, orig_rescan = X.retrain_test, X.rescan_test
orig_smi, orig_verify = X.nvidia_smi_info, X.run_verify_unlocker
orig_update, orig_installer = X.update_cmpunlocker, X.run_installer
globals()["wait_for_gpu"] = lambda: "0000:0a:00.0"
X.detect_gpus = lambda: ["0000:0a:00.0"]
X.get_gpu_uuid = lambda: "GPU-DEMO-UUID-0001"
X.check_link = lambda b: ({"lnksta_speed": "5GT/s", "lnksta_width": "x4", "lnksta_gen": 2,
"lnkcap_speed": "8GT/s", "lnkcap_width": "x16",
"lnksta_raw": "LnkSta: Speed 5GT/s, Width x4, TrErr-",
@@ -274,6 +284,7 @@ def demo(args):
finally:
globals()["wait_for_gpu"] = orig_wait
X.detect_gpus, X.check_link = orig_detect, orig_check
X.get_gpu_uuid = orig_uuid
X.aer_snapshot, X.dmesg_capture, X.dump_config = orig_aer, orig_dm, orig_cfg
X.retrain_test, X.rescan_test = orig_retrain, orig_rescan
X.nvidia_smi_info, X.run_verify_unlocker = orig_smi, orig_verify
@@ -289,7 +300,8 @@ def main():
help="tool check + package install (requires sudo) + harness clone, then exit")
ap.add_argument("--demo", action="store_true", help="run pipeline with fake hardware (self-test)")
ap.add_argument("--nvflash", help="path to nvflash binary")
ap.add_argument("--serial", help="override serial (skips nvflash auto-read)")
ap.add_argument("--serial", help="override physical serial recorded in serial.txt "
"(folder stays UUID-named)")
ap.add_argument("--skip-bios", action="store_true", help="skip VBIOS backup")
ap.add_argument("--vulkan", choices=("ask", "always", "never"), default="ask",
help="5-min Vulkan VRAM test policy (default ask, runs as last step)")