Skip to content

DMA Termination and Synchronization

DMA termination stops outstanding DMA transactions, while synchronization ensures that asynchronous completion activity has reached a safe quiescent point before client resources are released.

These are separate lifecycle operations.

Stopping DMA hardware alone is not sufficient for safe cleanup because completion processing, deferred callbacks, or other provider-specific activity may still be pending or running after the hardware transfer has stopped.


Termination and Synchronization Lifecycle

The complete shutdown lifecycle separates client shutdown, DMA termination, synchronization, and resource cleanup.

DMA Termination and Synchronization Lifecycle

The key boundary is between termination and synchronization:

Terminate DMA
Outstanding DMA Work Stopped or Retired
Completion Processing May Still Exist
Synchronize
DMA-Related Activity Quiescent
Safe Client Cleanup

Termination stops the DMA transaction lifecycle.

Synchronization closes the remaining asynchronous execution lifetime before client resources are reclaimed.


Why Stopping DMA Hardware Is Not Enough

DMA hardware execution and software completion processing have separate lifetimes.

A transaction may progress through:

DMA Hardware Completion
Cookie Completion
Deferred Completion Processing
Callback Execution
Descriptor Finalization

When termination occurs, stopping or aborting the DMA controller prevents outstanding hardware activity from continuing.

However, software completion activity may already have been scheduled.

For example:

DMA Hardware
    STOPPED

Deferred Callback
    PENDING or RUNNING

If the callback references a DMA buffer or client context, releasing those resources immediately after hardware termination can cause use-after-free or other lifetime violations.

Safe cleanup therefore requires both:

  1. Termination of outstanding DMA activity.
  2. Synchronization of remaining completion activity.

Client API Model

The DMA Engine framework exposes three related client APIs:

API Terminates DMA Synchronizes Completion Activity Safe Cleanup Boundary
dmaengine_terminate_async() Yes No No
dmaengine_synchronize() No Yes After the corresponding termination
dmaengine_terminate_sync() Yes Yes Yes

The exact termination and synchronization mechanisms are implemented by the DMA controller driver.


dmaengine_terminate_async()

dmaengine_terminate_async() requests termination of outstanding DMA activity.

Conceptually:

DMA Client
dmaengine_terminate_async()
device_terminate_all()
Controller-Specific Termination
return

The controller driver may need to:

  • Stop or abort an active hardware transfer.
  • Prevent queued transactions from becoming active.
  • Retire outstanding descriptors.
  • Update controller-specific software state.
  • Perform termination-side descriptor bookkeeping.

A successful return means that the controller termination operation returned successfully.

It does not guarantee that:

  • Deferred completion processing has quiesced.
  • A pending callback has executed.
  • A running callback has returned.
  • Client resources referenced by old DMA activity are safe to release.

Therefore:

dmaengine_terminate_async()
Termination Boundary

NOT

Safe Resource Cleanup Boundary

dmaengine_synchronize()

dmaengine_synchronize() establishes the synchronization boundary after termination.

Conceptually:

dmaengine_synchronize()
device_synchronize()
Controller-Specific Synchronization
QUIESCENT

Depending on the provider implementation, synchronization may include:

  • Waiting for required hardware quiescence.
  • Synchronizing interrupt processing.
  • Synchronizing deferred completion processing.
  • Waiting for running callbacks.
  • Preventing pending deferred callbacks from executing.
  • Reclaiming terminated descriptors.

These operations do not imply a generic fixed ordering.

The controller driver determines how its hardware and completion mechanisms reach the required quiescent state.


dmaengine_terminate_sync()

dmaengine_terminate_sync() combines termination and synchronization.

Conceptually:

dmaengine_terminate_sync()
        ├── dmaengine_terminate_async()
        └── dmaengine_synchronize()
Safe Cleanup Boundary

This is appropriate when the caller can complete both operations in the current execution context.

When termination must occur separately from synchronization, the client can instead use:

ret = dmaengine_terminate_async(chan);
if (ret)
    return ret;

/*
 * Perform synchronization later from an execution context
 * suitable for the provider's synchronization requirements.
 */
dmaengine_synchronize(chan);

The client must follow the calling-context requirements of the DMA Engine API and the synchronization mechanisms used by the provider.


Controller Driver Operations

The corresponding provider operations are part of struct dma_device.

Conceptually:

DMA Engine Client API             Controller Driver Operation

dmaengine_terminate_async()
        └───────────────────────► device_terminate_all()


dmaengine_synchronize()
        └───────────────────────► device_synchronize()


dmaengine_terminate_sync()
        ├── terminate_async()
        └── synchronize()

There is no separate controller operation corresponding directly to dmaengine_terminate_sync().

The synchronous client API composes termination and synchronization.


Descriptor State During Termination

Termination may occur while descriptors are at different lifecycle stages.

Descriptor State Main Termination Concern
Submitted Retire queued work before it can be issued.
Issued Prevent queued work from becoming active later.
Active Stop or abort hardware execution and retire the transaction.
Completed / callback pending Hardware execution may already be complete, but completion processing may still require synchronization.

The exact descriptor states and queues are provider-specific.

DMA Engine does not require every controller driver to use the same internal descriptor lists.

Submitted Descriptor

A submitted descriptor may not yet have reached hardware execution.

Termination must prevent it from later progressing into the active state.

Submitted
Terminate
Retired

No hardware abort may be necessary for that descriptor, but its software lifecycle still needs to be handled correctly.

Issued Descriptor

An issued descriptor may be waiting behind another active transaction.

Termination must prevent it from becoming active after the current hardware transfer is stopped.

Issued
Terminate
Must Not Become Active

Stopping only the current hardware transfer without retiring queued work could allow another descriptor to start afterward.

Active Descriptor

An active descriptor may require controller-specific hardware termination.

Active
Stop / Abort Hardware
Retire Transaction

The transfer may have completed only partially when termination occurs.

Termination must not be treated as equivalent to normal successful completion.

Completed Descriptor with Pending Callback

A descriptor may already have completed at the hardware and cookie levels while its deferred callback is still pending.

Hardware Complete
Cookie Complete
Callback Pending
Termination / Synchronization

Termination cannot undo an already recorded completion.

The remaining concern is the lifetime of deferred completion processing and resources referenced by the callback.


Completion and Termination Races

DMA completion and termination may occur concurrently.

For example:

Termination Path                 Completion Path

terminate
    │                           Hardware Completion
    │                                  │
    └──────────── race ────────────────┘

The controller driver must serialize descriptor state transitions so that a descriptor is not incorrectly processed through conflicting completion and termination paths.

Depending on the implementation, locking may protect:

  • Descriptor ownership.
  • Queue membership.
  • Active descriptor identity.
  • Completion decisions.
  • Termination decisions.

Conceptually:

                   ACTIVE
          ┌──────────┴──────────┐
          │                     │
   Completion Path       Termination Path
          │                     │
          └──── serialized ─────┘
          ┌──────────┴──────────┐
          ▼                     ▼
      Completed             Terminated

The exact locking and state transitions remain controller-specific.


Locking Does Not Replace Synchronization

Locking protects software state consistency.

Synchronization protects asynchronous execution lifetime.

These are different responsibilities:

Lock
Serialize Descriptor State Transitions


Synchronize
Wait Until Relevant Asynchronous
Execution Has Quiesced

A completion callback may execute outside the controller descriptor lock.

Therefore, successfully acquiring the lock during termination does not prove that an already scheduled or running callback has finished.


Callback Synchronization

A callback can be in different states when synchronization begins:

Callback Pending
May Be Prevented from Executing


Callback Running
Must Finish
Synchronization Returns

The exact behavior depends on the provider's deferred completion implementation.

For example, a virt-dma implementation using tasklets can synchronize tasklet execution so that pending or running completion activity no longer exists when synchronization returns.

The important guarantee is quiescence, not that every previously scheduled callback must execute.


Client Operational State

DMA Engine transaction state does not represent the operational state of the DMA client.

A client that resubmits DMA from its callback must prevent new transactions before beginning termination.

A useful client lifecycle is:

RUNNING
STOPPING
Prevent New DMA Submission
Terminate
Synchronize
STOPPED

The client state answers:

Is this driver still allowed to create new DMA work?

Transaction status answers a different question:

What happened to a particular DMA transaction?

Therefore, APIs such as dmaengine_tx_status() should not be used as a replacement for client shutdown state.


Callback-Driven Resubmission

Consider a client callback that submits another DMA transaction:

static void dma_callback(void *arg)
{
    struct my_device *dev = arg;

    if (READ_ONCE(dev->dma_state) != MY_DMA_RUNNING)
        return;

    my_dma_submit_next(dev);
}

The shutdown path must first prevent callback-driven resubmission:

Set Client State to STOPPING
Prevent New DMA Work
Terminate Outstanding DMA
Synchronize
Release Resources

The exact synchronization primitive used to protect the client state depends on the driver's concurrency model.

A plain state variable should not be assumed to provide sufficient synchronization without considering the execution contexts that access it.


Client Resource Lifetime

DMA shutdown is fundamentally a resource-lifetime problem.

A descriptor may reference:

DMA Descriptor
    ├── DMA Buffer
    ├── Callback Function
    └── Callback Parameter
       Client Context

Different execution paths may still access these resources:

DMA Hardware ───────────────┐
IRQ / Completion Processing ├──► Client Resources
Deferred Callback ──────────┘

Before releasing a resource, every asynchronous execution path that may reference it must have quiesced.

A typical cleanup sequence is:

Stop New DMA Submissions
Terminate Outstanding DMA
Synchronize
Release DMA Buffers
Release Callback / Client State
Release DMA Channel

The exact resource cleanup order is driver-specific, but the lifetime requirement remains the same.


Descriptor Object Lifetime

Transaction termination does not imply immediate descriptor destruction.

These concepts must remain separate:

Transaction State
Descriptor Object Lifetime
Cookie Identity

A provider may retire a transaction while retaining the descriptor object for later reclamation.

Therefore:

Transaction Terminated
Descriptor Immediately Freed

DMA clients must follow the DMA Engine ownership model and must not assume they can manually free a submitted provider descriptor.


virt-dma Termination Model

virt-dma provides reusable helpers for DMA controller drivers.

Relevant termination and synchronization helpers include:

  • vchan_next_desc()
  • vchan_terminate_vdesc()
  • vchan_get_all_descriptors()
  • vchan_synchronize()

A virt-dma controller may move descriptors into:

desc_terminated

and reclaim them later during synchronization.

Conceptually:

Outstanding Descriptor
Termination
desc_terminated
vchan_synchronize()
Descriptor Reclamation

This is an implementation model provided by virt-dma and is not mandatory for every DMA controller.


Controller Implementation Example

A virt-dma-based controller may need to treat the descriptor associated with current hardware execution differently from descriptors that are only queued.

One implementation pattern can look like:

Stop / Abort Hardware
Handle Current Descriptor
Collect Remaining Descriptors
Move Descriptors into
Termination-Side State
Return from Termination
Synchronize Later
Reclaim Descriptor Objects

Some controller implementations may update DMA cookie bookkeeping while retiring a descriptor.

This does not mean that termination is equivalent to normal successful completion.

Cookie accounting, transaction outcome, callback execution, and descriptor lifetime are separate concepts.


Common Misconceptions

Termination Means the Callback Cannot Run

Not necessarily.

Completion processing may already be pending or running when termination occurs.

Synchronization is required to establish the callback quiescence boundary.

Hardware Stopped Means Resources Are Safe to Free

Not necessarily.

A deferred callback may still reference the DMA buffer or client context.

Not necessarily.

Cookie bookkeeping records transaction progress for DMA Engine status tracking.

It does not by itself describe the complete transaction result or descriptor lifetime.

Termination Immediately Frees the Descriptor

Not necessarily.

Provider implementations may retain terminated descriptor objects until later reclamation.

Holding the Descriptor Lock Makes Cleanup Safe

Not necessarily.

The lock may protect descriptor state while callbacks execute outside that lock.

Synchronization Stops New Client DMA Submissions

No.

The DMA client is responsible for preventing its own callbacks, workers, IRQ paths, or threads from producing new DMA transactions during shutdown.


Summary

DMA termination and synchronization form two distinct shutdown phases.

Client STOPPING
Prevent New DMA Work
Termination
Outstanding DMA Transactions Retired
Synchronization
DMA-Related Asynchronous Activity Quiescent
Safe Client Cleanup

The most important rules are:

  • Termination stops or retires outstanding DMA transactions.
  • Synchronization establishes the quiescent boundary required for safe cleanup.
  • Hardware termination does not automatically stop already pending software completion processing.
  • Completion and termination may race and must be serialized by the controller implementation.
  • Locking protects state consistency but does not replace execution synchronization.
  • DMA clients must prevent new DMA work before beginning shutdown.
  • Client resources must remain valid until every DMA-related asynchronous execution path that may reference them has quiesced.
  • virt-dma provides one implementation model but does not define mandatory behavior for every DMA controller.