Zephyr OS Asynchronous Runtime PM: Distinguish a Queued Suspend from a Running Callback

A delayed runtime-PM put can return before the device has suspended. If another user arrives during that delay, the pending suspend may be cancelled. If the suspend callback has already started, acquiring the device follows a different path and may have to wait.

For a Zephyr OS driver, that distinction explains why closely spaced requests can produce different callback traces without a reference leak. This article concerns the ordinary asynchronous runtime-PM path in v4.4.0, not a measured power result or a general guide to system sleep.

Alternative runtime-PM arrival states: pending suspend can be canceled, an executing callback may require waiting; both converge on result and subsequent I/O checks.
Original conceptual engineering diagram. Proposed review method, not a measured result.

Interpret the asynchronous return at the right boundary

The tagged runtime-PM interface describes pm_device_runtime_put_async() as scheduling suspension when the device is no longer required. Its delay is a minimum before triggering the action. In pre-kernel operation the asynchronous request instead behaves synchronously.

Therefore a zero return in ordinary runtime operation must not be logged as proof that the power rail is already off. It can describe successful scheduling, and runtime PM being unavailable or disabled can also make these helpers no-ops. Record whether the feature is enabled before interpreting a missing callback as a failure.

A hypothetical sensor burst illustrates the distinction. The final sample releases its usage reference with a delayed put, but another acquisition arrives before the delay expires. Avoiding a suspend/resume pair in that interval can be the intended behavior rather than a lost suspend event.

Trace whether cancellation beat callback execution

The tagged implementation marks the ordinary asynchronous path as SUSPENDING and schedules delayable work. A later get attempts to cancel that work. If the callback is not running, it restores ACTIVE without an unnecessary suspend operation. If work is already running, the normal thread path waits for the state transition before proceeding.

This gives two distinct test cases. In the first, inject a request while suspension is still delayed and expect the request to avoid the pending transition. In the second, hold the test driver's suspend callback at a controlled point and inject the request after entry. The second case needs a completion dependency that the first does not.

Do not collapse those observations into one timing number called resume latency. Report whether the request encountered queued work, an executing suspend or an already-suspended device. The engineering explanation depends on that starting state.

Keep callback dependencies compatible with the PM path

A callback that waits for work scheduled on the same blocked execution path can create a circular dependency. Review its locks, workqueue use and completion mechanisms before increasing timeouts. A dedicated PM workqueue configuration changes scheduling context but does not automatically make arbitrary dependencies safe.

The public API warns that a get may fail with -EWOULDBLOCK where blocking is disallowed. An ISR must not assume that a preceding asynchronous put leaves the next get equivalent to an immediate thread-context acquisition. Handle the actual result and defer work when the product's design requires a sleep-capable path.

These are dependency checks, not recommendations to manipulate internal PM state. Let the framework own its state machine and use supported interfaces rather than manually clearing a suspending flag to bypass a wait.

Treat callback failure as a separate outcome

In the inspected asynchronous worker, a failing suspend callback restores an active state and increments usage; the worker also asserts successful suspension. An earlier successful scheduling return cannot retrospectively report this later callback result to its original caller. A product must qualify its driver callbacks and fault behavior rather than assuming asynchronous initiation certifies completion.

For proposed target tests, capture request arrival, get/put results, callback entry and exit, and the first subsequent real I/O. Exercise queued cancellation separately from a request racing an executing callback. Include configuration identity and bounded instrumentation overhead.

The acceptance question is narrow: does each arrival state follow the documented coordination path and leave the next operation usable? Current consumption, domain shutdown and worst-case response time require their own measurements. They cannot be inferred from a successful delayed-put call or from the absence of one suspend callback.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *