Deep sleep, wakelocks and managed power mode land in Pantavisor

Pantavisor now has a power management subsystem, landed on master in pantavisor#768 and built on the mainline kernel wakelock contract.

It sits in Pantavisor rather than beside it because Pantavisor already owns the operations that must not be interrupted by a suspend — over-the-air updates, Hub check-ins, container lifecycle, shutdown. Those are the same things a hand-rolled suspend setup usually has to be taught about separately.

What landed

A power.mode setting with three modes:

mode behaviour
disabled no power management at all
locks (default) Pantavisor holds a kernel wakelock across activity that must not be interrupted — hub roundtrips, updates, metadata syncs, shutdown, an open debug shell
managed everything locks does, plus opportunistic suspend (/sys/power/autosleep) with a scheduled RTC wake to poll the Hub

Every scope refcounts down onto a single kernel wakelock, so a sysfs write only happens on the 0↔1 edges.

In managed, the device suspends to RAM whenever nothing is holding it awake and wakes itself on a timer to check in. On wake, a wake window keeps it up long enough for the network to re-associate and at least one Hub roundtrip to complete, bounded by a hard cap so an unreachable Hub cannot pin the device awake indefinitely.

An update in flight holds the device awake for its whole duration — download, install, and the post-reboot test phase — so a device on a short sleep cycle still applies updates without being suspended part-way through.

Also in:

  • power.wake.run_window — after the wake’s own work finishes, stay awake this much longer as a run window for containers. Unmodified containers get a predictable slice of runtime.
  • GET /wakelocks on the local control socket, reporting mode, held scopes and managed state.
  • Config under power.wake.*, power.autosleep.* and power.devmeta.*. Durations accept a bare number of seconds or a literal like 30s, 10min, 1h.

What changes for existing devices

Nothing, unless you opt in.

The default is locks, and locks needs CONFIG_PM_WAKELOCKS. Without it Pantavisor logs one warning and degrades: every acquire and release becomes a no-op and the device behaves as before. Only managed fails loudly, and it has to be selected explicitly.

Even with kernel support present, a wakelock gates opportunistic suspend. Nothing enables autosleep unless managed is selected, so on a device that never suspends the lock has no effect.

One caveat: if something else on the system already drives /sys/power/autosleep, Pantavisor’s locks become an additional veto on suspend and will change the duty cycle. Use power.mode=disabled there.

What is coming next

Kernel-side enablement lives in the BSP layer (meta-pantavisor#422) behind a wakelocks feature flag that is off by default. Enabling it adds CONFIG_PM_WAKELOCKS and CONFIG_PM_AUTOSLEEP plus board-specific bits — on the Variscite VAR-SOM-MX8M-NANO, a device-tree patch enabling the SoC’s SNVS RTC, because the board’s external RTC alarm is not wired as a system wakeup source.

The next functional step is declarative cadence: rather than one global wake interval, a container declares its own in its manifest and Pantavisor schedules around it — coalescing so a two-minute container interval rides an existing wake instead of adding its own, and closing a window early once the container has gone idle rather than running out the full budget. That work exists on a branch and has been exercised on hardware; it is not submitted yet.

Further out: freeze/thaw hardening so wake windows are exclusive rather than shared, wake-reason reporting, and a logind inhibitor bridge so stock system software participates unmodified.

How finished is this?

locks is simple and we are reasonably confident in it.

managed should be treated as early. It is currently enabled and validated end-to-end on NXP i.MX — specifically an i.MX8M Nano, where it suspends, wakes on schedule, consumes an over-the-air update, reboots and resumes cycling. Other platforms need their own enablement work before managed is realistic.

Suspend-to-RAM is a whole-stack property: SoC power domains, a PSCI backend in firmware, a wakeup-capable RTC wired as a wakeup source, and every driver implementing suspend and resume correctly. The last one tends to be where the trouble is — we have seen an out-of-tree WiFi driver stall the freeze path until the watchdog reset the board, which is why autosleep is deferred for a settle period after boot rather than enabled as soon as the system looks idle.

Known rough edges:

  • The knobs interact. Setting the wake interval equal to the maximum awake time produces a device that cycles but barely sleeps. Some combinations warn at startup; not all do.
  • Queued revisions are consumed roughly one per wake — after an update finishes the device sleeps rather than draining the rest of the queue immediately. This is straightforward to improve and is on the list.
  • Per-container accounting, quiescence-based closing and real scheduling are cadence work, not in this drop.

locks should be safe to try on anything. managed is worth trying on a bench board you can power-cycle. If you do, we are interested in what your SoC does — the validation so far covers one board, and reports from other platforms are the most useful input right now.