Candidate shutdown path source audit, 2026-10-02
Recorded at 2026-10-02T17:33:48Z. Evidence class: read-only host source,
installed configuration and candidate DTB inspection. No board input, serial,
build, reset or new physical observation. Restart, callback execution and the
cause of the interrupted return remain UNVERIFIED.
Worktree /home/jadams/tmp/k230-mainline-root-path, branch
audit/mainline-root-path, base 9e9985c46838c58838e5395572cec4492ee47fcc.
Only this file is owned. No board or build slot was reserved. The completed
cached start-status report was reused as directed by the coordinator.
Exact candidate and observation boundary
Inspection used these installed artifacts, not an assumed upstream driver:
- Kernel
/nix/store/4wkhxf55y1abg1kg2xd0acsfjqr64j0h-linux-riscv64-unknown-linux-gnu-7.3.0-rc5;Imageis 38,530,560 bytes, SHA-25670a81b2172710c64463b53693e2e505a4d82ae2f7b644b2fc93cee9016b05330. - Source
/nix/store/jvz4v73g8a67pqwm06v079h6s1cpqr9s-linux-mainline-k230-drm-src, Linux pin72d3fcf802c45d00b300f25b848a93c3a2bd7c7eplus the repository’s optional K230 display/power/restart changes. - Configuration at
/nix/store/5wfn6k1lm9fvbwny2qk52admhwm5q4rm-linux-riscv64-unknown-linux-gnu-7.3.0-rc5-dev/lib/modules/7.3.0-rc5/build/.config, SHA-256c5c128ed8b9701f78a0b8bd4f18dacd0d2407ae90eda79a35bba2d9f5ffbeae7. - Bundle
/nix/store/asj7l4zj5jrjkgng4nrcx3y72p7jf7aa-k230-mainline-drm-trial-boot-files; itsk230-tdisplay-mainline-drm.dtbSHA-256 is48e3d470264db4f816c428a66d72852b5a283ebf679f647e65725573f70f89a1. - Matching system
/nix/store/v9qc1sf0iz53s3x6g6vwfyaxghkfpnyk-nixos-system-nixos-26.11.20260919.20b1ddd.
The committed physical minimal report
records returned receipt, true, proc setup and uptime, then userspace
Rebooting. without a candidate kernel restart announcement before operator
intervention and serial disconnect. It does not record a completed automatic
return deadline. Independent normal recovery, boot ID
08f9455a-1044-4d72-b7ae-bc70d611a8e2, protected hashes and reviewed camera
Home are separate evidence. The dispatch audit
places that userspace message immediately before the reboot syscall; it is
not a kernel entry or callback marker. No private capture was read for this
follow-up.
Before the restart callback
All paths below are relative to the exact source above. kernel/reboot.c:101–106
and 288–299 order reboot notifiers, usermode-helper disable, device shutdown,
restart-prepare callbacks, reboot-CPU migration and syscore shutdown before
Restarting system. Only then come kmsg dump and RISC-V machine_restart() /
do_kernel_restart() (arch/riscv/kernel/reset.c:19–29). The K230 callback’s
terminal loop is therefore downstream of the missing announcement, assuming
that announcement could still reach the capture. Console loss is not excluded.
drivers/base/core.c:4875–4947 has important gaps in initcall_debug tracing:
wait_for_device_probe()drains deferred work, waits for probe count zero and synchronizes async probes (drivers/base/dd.c:816–824), then probing is blocked and cpufreq suspended. These precede all device trace lines.- Devices are walked in reverse registration order, not DT address order. Parent and device mutexes are acquired before any trace line.
pm_runtime_get_noresume()/pm_runtime_barrier()precede the line. The latter can cancel work synchronously or wait without a local timeout for runtime suspend/resume/idle completion (drivers/base/power/runtime.c:1424–1484). A pending resume can run here.- With
initcall_debug, classshutdown_preor bus/drivershutdownis printed immediately before its callback. There is no callback-exit line. Platform devices print the bus entry even if their driver is unbound or lacks.shutdown;platform_shutdown()simply returns in those cases (drivers/base/platform.c:1527–1537).
Consequently no device lines leaves probe drain, cpufreq, the first locks or
runtime barrier, earlier preparation, and console visibility unresolved. A
last device line leaves both that callback and the next device’s unprinted
locks/barrier unresolved. drivers/base/syscore.c:117–131 prints
PM: Calling <symbol> before each syscore shutdown callback; its list mutex
also precedes those lines. None of these are completion markers.
Enabled nodes and actual driver hooks
fdtget on the bundle DTB and the installed .config gave:
| Candidate node | Available resources | Shutdown path in exact source |
|---|---|---|
/soc/sdhci1@91581000 | okay, canaan,k230-dw-mshc, IRQ 144/type 4; clock phandle 6 IDs 31/13; reset phandle 7 ID 9 | Kendryte host has probe/remove/PM operations, no platform shutdown. SD card MMC bus and mmcblk shutdown still apply. SD0 at 91580000 is disabled. |
/soc/usb@91500000, /soc/usb@91540000 | Both okay, canaan,k230-otg; IRQs 173/174/type 4; clock phandle 6 IDs 16/17; reset phandle 7 IDs 11/12 | Compatible matches DWC2 in drivers/usb/dwc2/params.c:366; platform.c:808 assigns dwc2_driver_shutdown. |
/soc/vo@90840000, /soc/dsi@90850000 | Both okay; VO IRQ 133/type 4 | Canaan VO and DSI platform drivers have no shutdown (canaan_vo.c:918, canaan_dsi.c:863). |
/soc/dsi@90850000/panel@0 | canaan,universal, absent status (available) | Panel DSI driver has probe/remove but no shutdown. DSI core installs its driver wrapper only when a panel supplies .shutdown (drm_mipi_dsi.c:2054–2055). |
/display-subsystem | okay, canaan,display-subsystem, power domain phandle 13/index 2 | Master has probe/remove but no shutdown (canaan_drv.c:391–399). |
/soc/power-controller@91103000 | canaan, k230-sysctl-power, absent status (available), phandle 13 | K230 provider has probe and managed cleanup, no shutdown. |
CONFIG_MMC, MMC_BLOCK, MMC_SDHCI_OF_DWCMSHC_KENDRYTE, USB_DWC2,
USB_DWC2_DUAL_ROLE, DRM_CANAAN, DRM_CANAAN_DSI,
DRM_PANEL_CANAAN_UNIVERSAL, SOC_K230_PM_DOMAINS, PM,
PM_GENERIC_DOMAINS, RESET_K230 and RISCV_SBI are all built in (y).
Availability/configuration/matching are not proof of successful physical
binding. DT IRQ values are interrupt-specifier IDs, not measured IRQ activity.
The concrete waits are:
- SD card:
drivers/mmc/core/bus.c:143–161calls the bound card driver’s shutdown (block.c:3293,3333), stops host detection, then SD bus shutdown (sd.c:1838→mmc_sd_suspend→_mmc_sd_suspend).mmc_queue_suspendquiesces the block queue and claims/releases the host to drain outstanding requests (queue.c:483–493). Host ownership waits withschedule()and no local timeout (core.c:791–830), then runtime-resumes the host. Detection stop callscancel_delayed_work_sync(core.c:2357–2369). SD suspend claims the host again and either sends supported power-off notification or deselects cards, then powers off (sd.c:1706–1732,1746–1758). Request completion waits (core.c:381,408) depend on lower-layer completion/timeout progress; they are not locally bounded waits. The power-off busy poll has a 1000 ms limit, which does not bound host acquisition or all request completion. The host PHY initialization loop has 15,000 iterations with 10–15 us sleeps (sdhci-of-kendryte.c:142–179); it is not an assigned shutdown callback and does not bound the entire MMC shutdown path. - USB: if low-level hardware is enabled, DWC2 shutdown disables global
interrupts, calls
synchronize_irq, then disables PHY/clocks/regulators (platform.c:368–376,164–187). IRQ synchronization spins for hard IRQ completion and waits for threaded handlers without a local timeout (kernel/irq/manage.c:50–79,118–127). PHY/resource release can acquire further framework locks; runtime state and optional PHY presence are unknown. USB interface shutdown wrappers also depend on dynamically bound devices; the DT alone cannot enumerate those callbacks. - Display/power:
drm_atomic_helper_shutdownoccurs only in Canaan master unbind (canaan_drv.c:295–305), not ordinarydevice_shutdown. Remove and managed cleanup are not invoked merely by reboot. The master retains a runtime-PM reference after successful probe. Its runtime barrier and other devices’ barriers still run, so display-related locks/work are not excluded. Provider power-on/off polling is bounded to 1000 iterations withudelay(1)per loop (k230-power-domains.c:64–113); repair polling applies only to AI. Those bounds assume executing CPU/MMIO progress. They establish neither physical completion nor invocation during this reboot.
Ranked next interpretation, not a cause finding
- Use the already assigned volatile
initcall_debugminimal trial to locate preparation progress on this exact bundle. Preserve the candidate receipt boundary; exclude the initial normal reboot and boot-time initcall lines. This separates visible device/syscore progress from wholly unobserved preparation, while preserving the lock/barrier gaps above. - If the final candidate device line identifies the SD card, prioritize the queue/host/detection/card-command path; if it identifies DWC2, prioritize IRQ synchronization/resource release. Neither line alone attributes a stall: the next device may be waiting before its line. Any further callback entry/exit or pre-barrier instrumentation needs a separately reviewed source change, matching build and bounded physical recovery.
- If device lines progress into
PM: Calling, narrow to syscore/pre-announcement work. If the candidate kernel announcement is captured, revisit restart dispatch and handler priority/registration with the existing dispatch audit. Direct atomic DRM shutdown and provider cleanup rank below these concrete paths because this candidate has no ordinary shutdown hooks for them.
The source supplies no evidence that USB, MMC, runtime PM, display or a reset register caused the failure. In particular, SD enumeration does not prove root-label reads, filesystem access, root startup or usable mainline login. No driver disable, guessed MMIO read or arbitrary interrupt survey is proposed. Retain the existing single-reboot/180-second normal-return controller bound; serial disconnect or missing return remains recovery-required, with no extra child command, retry, Ctrl-C or persistent environment change. The board operator owns recovery and protected normal postflight. This audit adds no physical pass and closes neither 5d.4 nor 5b.5.
Host commands and limits
Read-only commands were narrow rg -n / sed -n reads of the source files
named above, fdtget -l "$BUNDLE/k230-tdisplay-mainline-drm.dtb" /soc, and
fdtget -t s for compatible/status or -t x for interrupts/clocks/resets/
power-domains/phandle on the exact table nodes. Absent properties were checked
as FDT_ERR_NOTFOUND; corrected node names were taken from -l, not inferred
from unit addresses. Python pathlib/hashlib.sha256 read the installed Image,
configuration and DTB to reproduce the sizes/hashes above. No cmdline or raw
UART contents were published. Validation is the narrow OpenSpec command
openspec validate the-board-runs-a-mainline-kernel --strict plus
git diff --check; runtime tests are inapplicable to this documentation-only
source inspection.