Shared Reset Lines: Do Not Reset a Healthy Peer While Recovering One Peripheral
A recovery reset belongs to every device affected by the physical reset line, even when only one driver requested it. Map those consumers before attempting recovery. With Linux shared reset controls, an assert call may legitimately leave the line deasserted because a healthy peer still needs it released; successful API return is not proof that your device restarted.
Applicability: this article uses Linux v6.12 reset-controller APIs and reset core implementation. The two-consumer examples are hypothetical software/topology fixtures. Actual reset polarity, pulse width, affected state, and post-reset readiness must come from the selected controller, peripheral documentation, and board schematic.

1. Build the physical reset dependency graph
Start at the reset provider and follow the signal to every affected block. Include devices not represented by the failing driver’s immediate parent, downstream bridges, and functions within a multi-function component. A convenient reset name is not proof of a dedicated wire.
For each consumer, record whether it can tolerate reset while active, whether it performs DMA, what configuration is lost, and how it reports quiescence. Also record power or clock dependencies that may make the reset ineffective or unsafe in a particular state.
Choose the recovery unit from this graph. If resetting A also resets B, a local A-only recovery may be impossible while B remains active. The design needs a coordinated recovery operation, a device-local alternative, or a visible unavailable state until coordinated recovery becomes permissible.
2. Read the shared-control contract correctly
The v6.12 reset API documentation distinguishes shared reference-counted controls from exclusive direct control. Shared deassert/assert calls must balance. The first deassert releases the line; only the final matching assert can assert it again. A consumer cannot assume its own assert reset the hardware while another deassert request remains.
Consider two hypothetical consumers, A and B, each with one successful deassert. The shared count is two. A’s matching assert reduces it to one and leaves reset released for B. A must not then treat register defaults as established or claim that its recovery pulse occurred.
If B later becomes quiescent and balances its deassert with an assert, the count reaches zero and the provider can assert reset. Both consumers must be prepared for the resulting state loss. The count represents reset-release requests, not a complete model of whether either device is electrically or operationally safe to reset.
3. Do not mix level-control and pulse-control protocols
Linux also supports self-deasserting reset operations through reset_control_reset. Shared pulse controls use a different counted protocol: only the first trigger produces a pulse until participating calls have been balanced with reset_control_rearm. The v6.12 reset core implements the trigger count and rejects mixing this protocol with outstanding shared deassert usage.
A second successful pulse request can therefore be a no-op rather than another physical reset. Rearming is not a command that resets a device immediately. It makes a later trigger possible once the shared trigger accounting permits it.
Select one documented protocol for the shared resource and keep its accounting visible. Do not add reset_control_reset to a failure path that otherwise uses shared deassert/assert, hoping to force recovery past a peer’s claim. Bypassing the provider with a direct GPIO write defeats the ownership contract altogether.
4. Separate reference release from recovery authorization
Define a coordinator that knows the reset dependency graph and the device lifecycles. Before a reset that affects several consumers, stop new work, complete or safely cancel outstanding operations, and ensure the peer owners agree that their hardware state may be discarded.
Use explicit operation results such as recovered, recovery-deferred, or unavailable. If a peer cannot quiesce within the application policy, preserve that result rather than pretending that a shared assert succeeded physically. Do not repeatedly manipulate the count until a pulse happens.
After a coordinated reset, restore each consumer in a dependency-compatible order and verify its own readiness. Reset release is not the same as configuration restored, DMA safe, or first data valid. Keep stale completions and pre-reset application data associated with the old generation.
An exclusive reset handle changes framework ownership, not the physical fan-out. A sole software owner can still reset multiple hardware blocks. Never infer that “exclusive” means that only the requesting peripheral is connected.
5. Make acquisition and cleanup failures observable
Track calls, returns, and provider transitions separately. In v6.12, shared level-control counts change before the provider callback, and a callback error does not automatically roll those changes back. Do not blindly retry or infer accounting from success alone. Reconcile the exact failure path while affected consumers remain quiescent. Include probe failure, suspend, resume, and removal.
Optional reset handles require special interpretation. The API permits a missing optional reset to be represented by NULL and makes operations on it succeed without hardware action. That may be appropriate on a board that needs no reset control, but it cannot satisfy a recovery requirement that depends on a real physical reset.
A shared assert can also return success without a provider assert callback, so even a zero count is not a universal pulse guarantee. When status querying is supported, use its documented result and handle unsupported/error returns explicitly. A software count and a provider status value answer different questions. For electrical proof, observe the reset signal and a device-specific consequence under the agreed board conditions.
6. Use a peer-active test matrix
| Proposed case | Required interpretation |
|---|---|
| A fails while B retains deassert | A’s balanced assert does not establish a physical reset; B remains protected. |
| Both consumers quiesce and balance claims | Observe the intended shared reset and restore both consumers. |
| A resumes after a peer-triggered reset | A detects invalidated state and restores its required configuration. |
| Shared pulse requested twice without full rearm | Do not count two API successes as two hardware pulses. |
| Optional reset absent | Expose whether recovery is unsupported rather than claiming reset completion. |
Use a model fixture for count and failure-path checks before board testing. On hardware, keep B active with a safe observable workload while exercising only approved recovery cases. Check its continuity, error reporting, and configuration, not just whether A begins responding again.
Record every affected consumer, held claim, operation result, physical observation, and restoration outcome. A passing test should explain why the peer was protected or deliberately included in recovery.
No reset operation was executed for this article. The deliverable is a reset-consumer dependency graph and balanced lifecycle test matrix. If local recovery cannot be isolated, state that limitation clearly; shared-reset accounting is a protection mechanism, not a way to manufacture an independent reset that the board does not provide.