Peripheral Resume Before Its Bus: Restore Dependencies in the Right Order

Make resume dependencies explicit in both topology and callback phase. Linux can order a child after its parent and a consumer after a declared supplier, but that does not make a resource initialized in a later phase available to an earlier callback. Diagnose the first invalid dependency edge instead of adding an arbitrary delay.

Applicability: this procedure uses Linux v6.12 system device PM and device links. The controller, consumer, and auxiliary supplier below are hypothetical. It does not prescribe peripheral wake commands or electrical settling times; those remain separate part-specific requirements.

Parent B and supplier S both support consumer C; S noirq runs before C noirq, but a service restored only in S ordinary resume remains unavailable to C.
Hypothetical cross-phase counterexample derived from Linux v6.12 ordering contracts. It does not represent a measured trace or a device-specific wake sequence.

1. Draw the effective dependency graph

Begin with the device-model parent of the failing peripheral. Then add resources supplied by devices outside that parent chain: a shared controller, translation unit, auxiliary control interface, or other provider. Distinguish a real supplier dependency from two devices merely sharing one power domain.

The v6.12 device-PM guide specifies child-before-parent suspend and parent-before-child resume ordering. Each phase is processed across the devices before the next phase begins. Preparation and completion have their own traversal rules, so avoid treating every callback as one simple reverse list.

For each graph edge, write the resource the consumer needs and the earliest phase when it needs it. “C depends on S” is too vague. “C reads S’s control interface during resume_early, after S has restored that interface” is a reviewable requirement.

Inspect the actual registered topology and links, not only the source device tree. Firmware interpretation, subsystem registration, and driver behavior determine the objects participating in PM ordering. Save identities that let another engineer connect the trace back to those objects.

2. Represent non-parent suppliers deliberately

The Linux v6.12 device-link contract represents dependencies beyond parent/child relationships. Managed links include supplier-driver presence and PM ordering; stateless links can request ordering without that presence dependency. Runtime-PM integration is a separate option, selected with DL_FLAG_PM_RUNTIME.

Thus, a link used for system transition ordering does not automatically establish every runtime ownership requirement. Conversely, adding runtime integration changes how long the supplier must remain active. Choose flags from the actual dependency and lifecycle rather than copying a nearby driver’s combination.

Do not create links during an uncontrolled suspend/resume transition. Review link creation, failed probe, unbind, and removal under the documented lifetime rules. A link that exists only after the failing callback runs cannot order that earlier callback.

Check for an existing relationship created by firmware or subsystem code before adding another owner. An unexplained duplicate or cyclic dependency can create a new probe or lifetime problem while obscuring the original resume defect.

3. Expose the cross-phase counterexample

Consider hypothetical supplier S and consumer C with a correctly declared S-before-C resume dependency. S has no readiness work in resume_noirq; it restores the needed service only in its ordinary resume callback. C nevertheless tries to use that service in resume_noirq.

The ordering can be perfectly obeyed and C can still fail. S’s noirq phase occurs before C’s noirq phase, but S’s ordinary resume belongs to a later global phase. Waiting inside C’s noirq callback for that later callback to run can prevent the system from ever reaching it.

This is an engineering deduction from the phase contract, not a reported Linux bug. It shows why “the supplier resumes first” must name the phase and the resource-ready postcondition. A dependency edge is necessary for ordering, but it cannot turn future work into completed work.

Repair the phase contract: move C’s dependent operation later, or restore the required subset of S’s service earlier if the framework, transport, and hardware permit it. Check all prerequisites of that earlier work. Moving code into noirq without its interrupt or clock dependencies simply relocates the failure.

4. Specify readiness at callback return

A supplier callback must not return success while leaving an essential restoration step in an untracked worker that the consumer immediately needs. If asynchronous work is necessary, define a supported completion relationship before exposing the resource. Do not assume device ordering also waits for arbitrary work queued by a callback.

Use named postconditions: registers accessible, transfer engine initialized, interrupt completion available, and child transactions admitted. Keep electrical readiness separate where a part needs additional qualification. A parent being active in software does not prove every downstream component has completed its own startup.

Review the reverse suspend direction too. The consumer must stop using a resource before its supplier removes it. An apparently correct resume sequence can coexist with a suspend-side race that corrupts state and only becomes visible after wake.

5. Trace edges rather than whole-system chronology

For each relevant callback, record device, phase, entry, exit, result, and resource-ready transition. At the consumer’s first dependent access, capture which supplier-ready condition it relied on. This is more decisive than comparing two unqualified “resume done” log lines.

Allow independent branches to run in parallel. A correct partial order does not require every device to follow one fixed global sequence. The test should assert supplier completion before the consumer’s dependent access, not an incidental total ordering from one successful boot.

Proposed fixture Expected finding
Delay supplier within a legal phase Dependent consumer access cannot overtake required completion.
Move readiness to a later phase in a model The cross-phase dependency is rejected before target use.
Remove a non-parent supplier link in a model The ordering assertion detects the missing edge.
Supplier restoration fails The consumer does not publish successful dependent I/O.
Unrelated branch resumes slowly No unnecessary dependency is inferred from coincidental timing.

Use model tests or reviewed fault hooks for deliberately broken orderings. Do not create invalid clock or power sequences on a production assembly. Any target delay injection must preserve the callback’s context and the hardware’s safe operating requirements.

6. Preserve the dependency contract through changes

Store the graph, phase-specific ready conditions, link flags, and successful/failed traces with the driver revision. Revisit them when a controller changes its resume phase, a supplier becomes optional, or a board variant moves a device onto another bus.

No system transition was executed for this article. The deliverable is a dependency graph with phase-indexed ordering assertions. It distinguishes a missing topology edge from a correctly ordered but premature consumer access, giving the repair a precise target without claiming that extra sleep time can replace readiness.

Similar Posts