Skip to content

DMA Engine APIs

Purpose

The Linux DMA Engine Framework provides a common programming interface for client drivers to perform DMA transfers without directly accessing hardware-specific DMA controller registers.

The framework abstracts different DMA controller implementations and exposes a unified set of APIs for channel allocation, transaction preparation, submission, execution, and completion.


#include <linux/dmaengine.h>

Typical Workflow

A typical one-shot slave DMA client combines long-lived channel configuration with a shorter per-transfer mapping and transaction lifecycle.

Driver Lifetime

Request Channel
Configure Slave DMA
READY


Transfer Lifetime

Obtain Buffer
DMA Map
Prepare Descriptor
Set Callback
Submit
Issue Pending
DMA Armed
Start Peripheral
DMA Active
Complete / Terminate
DMA Safe
Sync for CPU if required
Unmap
Consume / Release Buffer

dmaengine_slave_config() describes the peripheral side of the DMA channel, while DMA mapping and descriptor preparation describe an individual memory transaction.

For peripheral slave DMA, dma_async_issue_pending() does not necessarily mean that data is already moving. Actual transfer activity may still depend on DMA requests generated by the peripheral.

A useful client-side ordering is therefore:

Prepare
Submit
Issue Pending
DMA Armed
Enable Peripheral
Peripheral DMA Requests
DMA Transfer

The exact ordering is hardware-specific, but the client driver must coordinate the DMA transaction and peripheral state explicitly.

For the complete client-side architecture, resource lifetimes, completion boundary, and cleanup ordering, see:


API Quick Reference

Use the tables below to quickly locate the DMA Engine API or helper you need.

Channel Management

API Purpose
dma_request_chan() Request a DMA channel from the DMA Engine Framework.
dma_release_channel() Release a previously allocated DMA channel.

Slave Configuration

API Purpose
dmaengine_slave_config() Apply peripheral-side DMA configuration to a slave DMA channel.

dmaengine_slave_config()

Applies slave configuration to a DMA channel.

Prototype

int dmaengine_slave_config(struct dma_chan *chan,
                           struct dma_slave_config *config);

Parameters

Parameter Description
chan DMA channel being configured.
config Peripheral-side slave DMA configuration.

Return Value

Returns 0 on success or a negative error code when the controller cannot apply the requested configuration.

Description

dmaengine_slave_config() configures how a DMA channel accesses its peripheral endpoint. The generic configuration is dispatched through the DMA controller driver's device_config() operation.

For DMA_MEM_TO_DEV, the peripheral is normally described by the dst_* fields:

Memory -> Peripheral
          dst_addr
          dst_addr_width
          dst_maxburst

For DMA_DEV_TO_MEM, the peripheral is normally described by the src_* fields:

Peripheral -> Memory
src_addr
src_addr_width
src_maxburst

The address-width fields describe the peripheral-side transfer beat width; they do not describe the bit width of the DMA address.

The controller driver may save the configuration rather than immediately programming a complete hardware transaction. Transaction-specific information such as the memory DMA address, transfer length, and direction is supplied separately by a descriptor preparation API.

Conceptually:

dma_slave_config
        +
Transaction Information
        |
        v
Controller-Specific Descriptor Preparation
        |
        v
Hardware Descriptor

Example

struct dma_slave_config config = { };
int ret;

config.dst_addr = fifo_addr;
config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
config.dst_maxburst = 4;

ret = dmaengine_slave_config(chan, &config);
if (ret)
    return ret;

Notes

  • src_addr is normally used when the peripheral is the DMA source.
  • dst_addr is normally used when the peripheral is the DMA destination.
  • The DMA channel name does not itself determine transaction direction.
  • CPU MMIO virtual addresses must not be used as DMA peripheral addresses.
  • DMA-visible addressing may require platform or controller-specific address translation.
  • Slave configuration and transaction descriptors have different responsibilities and lifetimes.
  • Controller-specific width, burst, increment, and address encodings are handled by the DMA controller driver.

See also:


Transaction Preparation

DMA Engine provides multiple preparation APIs for different transfer types. dmaengine_prep_xxx() is commonly used as a family name in documentation rather than as a real function.

API Purpose
dmaengine_prep_slave_single() Prepare a one-shot slave DMA transaction using one DMA address range.
dmaengine_prep_slave_sg() Prepare a slave DMA transaction from a DMA-mapped scatter-gather list.
dmaengine_prep_dma_cyclic() Prepare a long-running cyclic DMA transaction with period-based callback notification.

Transaction Submission and Execution

API Purpose
dmaengine_submit() Submit a prepared DMA descriptor and return its transaction cookie.
dma_async_issue_pending() Make submitted transactions available for controller scheduling.

Transaction Status

API Purpose
dmaengine_tx_status() Query the current status and optional residue of a submitted DMA transaction.
device_tx_status() Controller operation that reports transaction status and optional progress information.
dma_cookie_status() Determine generic transaction status from channel cookie bookkeeping.
dma_async_is_complete() Compare a transaction cookie against the completed and used cookie boundaries.
API Purpose
dma_cookie_assign() Assign the next transaction cookie during descriptor submission.
dma_cookie_complete() Record completion of a DMA transaction cookie.

Termination and Synchronization

API Purpose
dmaengine_terminate_async() Terminate outstanding DMA transactions without establishing a complete synchronization boundary.
dmaengine_synchronize() Synchronize remaining DMA completion activity after termination.
dmaengine_terminate_sync() Perform termination followed by synchronization.
device_terminate_all() Controller operation that performs provider-specific transaction termination.
device_synchronize() Controller operation that establishes the provider-specific quiescent boundary after termination.

Core Objects

The DMA Engine Framework revolves around three primary kernel objects.

struct dma_device

Represents one DMA controller registered with the DMA Engine Framework.

Main responsibilities include:

  • Advertise DMA controller capabilities
  • Provide hardware-specific operation callbacks
  • Own one or more struct dma_chan objects
  • Register the DMA controller with the DMA Engine Framework

See also:


struct dma_chan

Represents one DMA channel provided by a DMA controller.

A client driver normally obtains a channel through dma_request_chan().

The returned channel object is later used for descriptor preparation and DMA transactions.

See also:


struct dma_slave_config

Describes the peripheral-side configuration of a slave DMA channel.

Important fields include:

  • src_addr and dst_addr for peripheral endpoints.
  • src_addr_width and dst_addr_width for peripheral transfer width.
  • src_maxburst and dst_maxburst for requested burst behavior.
  • device_fc for peripheral flow-control configuration where applicable.

The structure describes channel/peripheral configuration rather than an individual memory transaction.

See also:


struct dma_async_tx_descriptor

Represents one DMA transaction descriptor.

A descriptor describes a DMA transaction before it is submitted to the DMA Engine Framework.

Important descriptor state includes:

  • The DMA channel associated with the transaction.
  • The descriptor-specific tx_submit() operation.
  • Completion callback information.
  • The DMA cookie assigned during submission.

The descriptor is prepared first and submitted later.

Submission through dmaengine_submit() dispatches through the descriptor's tx_submit() callback.

See also:

struct dma_tx_state

Represents additional transaction state returned by a DMA status query.

The structure is commonly used with dmaengine_tx_status() to report progress information such as DMA residue.

It describes the transaction state at query time and should not be confused with struct dmaengine_result, which describes completion-result information delivered through a result-aware callback.

See also:


struct dmaengine_result

Represents completion-result information supplied to a result-aware DMA callback.

The structure contains:

  • The DMA transaction result.
  • The residue associated with the completion event.

It is used with dma_async_tx_callback_result.

Unlike struct dma_tx_state, which represents query-time transaction state, struct dmaengine_result describes the outcome associated with a completion callback.

See also:


Linux Source

Important source files include:

Location Purpose
include/linux/dmaengine.h Public DMA Engine objects, callbacks, and API declarations.
drivers/dma/dmaengine.c DMA Engine Framework implementation.
drivers/dma/dmaengine.h Internal DMA Engine helpers used by DMA controller implementations.
drivers/dma/of-dma.c Device Tree DMA provider registration and channel lookup support.
drivers/dma/virt-dma.c Generic virtual DMA helper framework used by many DMA controller drivers.
drivers/dma/virt-dma.h virt-dma descriptor, channel, termination, and synchronization helpers.
drivers/dma/ Hardware-specific DMA controller drivers.

Channel APIs

dma_request_chan()

Requests a DMA channel from the DMA Engine Framework.

Prototype

struct dma_chan *dma_request_chan(struct device *dev,
                                  const char *name);

Parameters

Parameter Description
dev Client device requesting DMA services.
name Logical DMA channel name, usually matched through dma-names.

Return Value

Returns a pointer to struct dma_chan on success, or an error pointer on failure.

Use IS_ERR() and PTR_ERR() to test and retrieve the error code.

Description

dma_request_chan() requests a DMA channel from the DMA Engine Framework.

When Device Tree is used, the framework:

  • Looks up the channel name in dma-names.
  • Reads the corresponding entry in dmas.
  • Locates the referenced DMA controller.
  • Invokes the provider-specific translation function.
  • Returns the corresponding struct dma_chan.

The function returns an existing DMA channel managed by the DMA controller driver. It does not create a new DMA channel.

Example

struct dma_chan *rx_chan;

rx_chan = dma_request_chan(dev, "rx");
if (IS_ERR(rx_chan))
    return PTR_ERR(rx_chan);

Notes

  • The channel name is a logical resource name rather than a hardware channel number.
  • The DMA specifier format is controller-specific.
  • The returned channel should later be released using dma_release_channel().
  • The function may return -EPROBE_DEFER if the DMA provider has not completed probe.

dma_release_channel()

Releases a DMA channel previously obtained by dma_request_chan().

Prototype

void dma_release_channel(struct dma_chan *chan);

Parameters

Parameter Description
chan DMA channel to release.

Return Value

This function does not return a value.

Description

Releases a DMA channel previously obtained by dma_request_chan().

After the channel has been released, the client driver must no longer access the corresponding struct dma_chan.

Example

dma_release_channel(rx_chan);
rx_chan = NULL;

Notes

  • Complete or terminate outstanding DMA transactions before releasing the channel.
  • Do not access the channel after it has been released.
  • The released channel becomes available for future allocation according to the DMA controller driver's allocation policy.

Transaction Preparation

DMA Engine provides preparation APIs for different transfer types.

Preparation creates and configures a DMA transaction descriptor. It does not submit the descriptor or start DMA hardware execution.

The generic slave-transfer lifecycle is:

DMA Mapping
Prepare Descriptor
dmaengine_submit()
dma_async_issue_pending()

For slave DMA, peripheral-side channel configuration and per-transfer information have different responsibilities:

dmaengine_slave_config()
        └── Peripheral-side configuration

dmaengine_prep_slave_single()
dmaengine_prep_slave_sg()
        └── Individual transaction information

The DMA controller driver combines both sources when constructing controller-specific hardware descriptors.

dmaengine_prep_slave_single()

Prepares a slave DMA transaction whose memory side is represented by one DMA address range.

Prototype

struct dma_async_tx_descriptor *
dmaengine_prep_slave_single(struct dma_chan *chan,
                            dma_addr_t buf,
                            size_t len,
                            enum dma_transfer_direction dir,
                            unsigned long flags);

Parameters

Parameter Description
chan DMA channel used for the transaction.
buf DMA-mapped memory address.
len Number of bytes in the memory range.
dir Slave DMA transaction direction, normally DMA_MEM_TO_DEV or DMA_DEV_TO_MEM.
flags Descriptor preparation flags such as DMA_PREP_INTERRUPT and DMA_CTRL_ACK.

Return Value

Returns a prepared struct dma_async_tx_descriptor on success.

Returns NULL if the DMA controller cannot prepare the requested transaction.

Description

dmaengine_prep_slave_single() provides a convenient interface for a slave DMA transaction whose memory side can be described by one DMA address and length.

The address supplied through buf must already be a DMA-visible address. For a streaming TX mapping, the client typically obtains it using dma_map_single(..., DMA_TO_DEVICE) and then prepares the DMA Engine transaction with DMA_MEM_TO_DEV. For RX, the corresponding directions are DMA_FROM_DEVICE and DMA_DEV_TO_MEM.

The DMA mapping direction and DMA Engine transfer direction belong to different APIs and describe different aspects of the operation.

Single-Range Representation

Internally, dmaengine_prep_slave_single() represents the supplied DMA address and length as a single scatter-gather entry and dispatches the transaction through the DMA controller driver's slave SG preparation operation.

dma_addr_t + len
One DMA SG Entry
device_prep_slave_sg()
DMA Controller Driver

Therefore, single does not imply one physical page, one controller transfer block, one hardware descriptor, or one hardware LLI. The provider may split the range into multiple hardware descriptors according to controller limitations.

Typical Usage

struct dma_async_tx_descriptor *desc;
dma_addr_t dma_addr;
dma_cookie_t cookie;
int ret;

dma_addr = dma_map_single(dev, buf, len, DMA_TO_DEVICE);
if (dma_mapping_error(dev, dma_addr))
    return -EIO;

desc = dmaengine_prep_slave_single(chan,
                                   dma_addr,
                                   len,
                                   DMA_MEM_TO_DEV,
                                   DMA_PREP_INTERRUPT |
                                   DMA_CTRL_ACK);
if (!desc) {
    ret = -EIO;
    goto err_unmap;
}

desc->callback = dma_complete;
desc->callback_param = context;

cookie = dmaengine_submit(desc);
ret = dma_submit_error(cookie);
if (ret)
    goto err_unmap;

dma_async_issue_pending(chan);

/* Keep the mapping valid until DMA can no longer access the buffer. */
return 0;

err_unmap:
dma_unmap_single(dev, dma_addr, len, DMA_TO_DEVICE);
return ret;

This example shows the preparation and submission sequence only. An asynchronous client must retain the mapping until completion or a synchronized termination boundary.

Notes

  • buf is a DMA address, not a CPU virtual address.
  • dmaengine_prep_slave_single() does not perform DMA mapping for the client.
  • DMA_TO_DEVICE / DMA_FROM_DEVICE belong to the DMA mapping API.
  • DMA_MEM_TO_DEV / DMA_DEV_TO_MEM belong to DMA Engine.
  • Configure the completion callback after descriptor preparation succeeds and before submission.
  • Check the cookie returned by dmaengine_submit() with dma_submit_error().
  • Keep the DMA mapping valid while DMA hardware may access the buffer.
  • After dma_async_issue_pending(), timeout or cancellation paths must establish an appropriate termination and synchronization boundary before unmapping the buffer.
  • DMA completion does not necessarily imply that the peripheral itself has completed its operation.

See also:


dmaengine_prep_slave_sg()

Prepares a slave DMA transaction whose memory side is represented by a DMA-mapped scatter-gather list.

Prototype

struct dma_async_tx_descriptor *
dmaengine_prep_slave_sg(struct dma_chan *chan,
                        struct scatterlist *sgl,
                        unsigned int sg_len,
                        enum dma_transfer_direction dir,
                        unsigned long flags);

Parameters

Parameter Description
chan DMA channel used for the transaction.
sgl DMA-mapped scatter-gather list describing the memory side.
sg_len Number of DMA-mapped segments supplied for transaction preparation.
dir Slave DMA transaction direction, normally DMA_MEM_TO_DEV or DMA_DEV_TO_MEM.
flags Descriptor preparation flags such as DMA_PREP_INTERRUPT and DMA_CTRL_ACK.

Return Value

Returns a prepared struct dma_async_tx_descriptor on success.

Returns NULL if the DMA controller cannot prepare the requested SG transaction.

Description

dmaengine_prep_slave_sg() prepares one slave DMA transaction whose memory side is represented by a previously DMA-mapped scatter-gather list.

The function does not perform DMA mapping.

The client or an owning subsystem must first establish the DMA-visible SG representation.

A typical raw SG mapping sequence is:

Original Scatterlist
        │ original count = nents
dma_map_sg()
        │ returns mapped_nents
DMA-Visible Segments
dmaengine_prep_slave_sg(..., mapped_nents, ...)

The sg_len argument therefore represents the mapped DMA segment count returned by dma_map_sg(), not the original number of SG entries.

Original vs Mapped SG Count

DMA mapping may merge original SG entries into fewer DMA-visible segments.

For example:

Original SG entries

SG0
SG1
SG2
SG3

nents = 4

        │ dma_map_sg()

DMA-visible segments

Segment 0
Segment 1
Segment 2

mapped_nents = 3

For a successful mapping:

0 < mapped_nents <= nents

The two counts have different responsibilities.

Operation Count
dma_map_sg() Original nents
dmaengine_prep_slave_sg() Mapped mapped_nents
dma_sync_sg_for_cpu() Original nents
dma_sync_sg_for_device() Original nents
dma_unmap_sg() Original nents

The mapped count belongs to the DMA-visible transaction representation.

The original count remains part of the DMA mapping lifecycle.

DMA-Visible SG Information

The DMA controller provider consumes DMA-visible information associated with the mapped scatterlist.

Important helpers include:

sg_dma_address(sg);
sg_dma_len(sg);

These values represent the device-visible address and length for a mapped DMA segment.

The provider should not reconstruct DMA addresses from CPU-side information such as:

sg_page()
sg->offset
sg->length

Conceptually:

CPU-Side SG Representation
──────────────────────────

page
offset
length

        │ DMA mapping

DMA-Visible Representation
──────────────────────────

sg_dma_address()
sg_dma_len()

Relationship to Slave Configuration

The SG list supplies memory-side transaction information while struct dma_slave_config supplies peripheral-side channel information.

For DMA_MEM_TO_DEV:

Mapped SG DMA address
Source / SAR
INC

config.dst_addr
Destination / DAR
NOINC

For DMA_DEV_TO_MEM:

config.src_addr
Source / SAR
NOINC

Mapped SG DMA address
Destination / DAR
INC

The DMA controller provider combines:

DMA-mapped SG
        +
dma_slave_config
        +
transfer direction
Controller-specific descriptor preparation

The exact SAR, DAR, increment, width, burst, and transfer-count encodings remain controller-specific.

Provider Dispatch

Conceptually:

dmaengine_prep_slave_sg()
device_prep_slave_sg()
DMA Controller Provider
Hardware Descriptor / LLI Chain

The provider iterates the mapped DMA segments and translates them into the representation required by its controller.

A mapped SG segment is not equivalent to one hardware descriptor.

Mapped SG Segment
        │ provider hardware constraints
One or More Hardware Descriptors / LLIs

A provider may split one mapped segment because of:

  • Maximum DMA block size
  • Address alignment
  • Transfer width
  • Burst restrictions
  • Controller-specific transfer limits

Therefore:

Original SG entry
DMA-mapped segment
Hardware DMA descriptor / LLI

Direction Mapping

DMA mapping direction and DMA Engine direction belong to different APIs.

For TX:

Layer Direction
DMA Mapping DMA_TO_DEVICE
DMA Engine DMA_MEM_TO_DEV

For RX:

Layer Direction
DMA Mapping DMA_FROM_DEVICE
DMA Engine DMA_DEV_TO_MEM

Typical TX Usage

struct dma_async_tx_descriptor *desc;
dma_cookie_t cookie;
int mapped_nents;
int ret;

mapped_nents = dma_map_sg(dev, sgl, nents, DMA_TO_DEVICE);
if (!mapped_nents)
    return -EIO;

desc = dmaengine_prep_slave_sg(chan,
                               sgl,
                               mapped_nents,
                               DMA_MEM_TO_DEV,
                               DMA_PREP_INTERRUPT |
                               DMA_CTRL_ACK);
if (!desc) {
    ret = -EIO;
    goto err_unmap;
}

desc->callback = dma_complete;
desc->callback_param = context;

cookie = dmaengine_submit(desc);
ret = dma_submit_error(cookie);
if (ret)
    goto err_unmap;

dma_async_issue_pending(chan);

/*
 * Keep the mapping valid until DMA can no longer access the SG
 * memory. Completion or synchronized termination must establish
 * the required lifetime boundary before unmapping.
 */
return 0;

err_unmap:
dma_unmap_sg(dev, sgl, nents, DMA_TO_DEVICE);
return ret;

Mapping Lifetime

The SG mapping must remain valid while DMA hardware may access the memory.

For a successful one-shot transfer:

dma_map_sg()
dmaengine_prep_slave_sg()
dmaengine_submit()
dma_async_issue_pending()
DMA completion
dma_unmap_sg()

If preparation or submission fails before issue:

DMA mapped
prep / submit failure
dma_unmap_sg()

No active DMA transfer needs to be terminated.

After issue:

DMA may access SG memory
timeout / cancellation
dmaengine_terminate_sync()
DMA and completion activity resolved
dma_unmap_sg()

Persistent Mapping

When an SG mapping remains active across repeated DMA operations, ownership may be synchronized without destroying the mapping.

Device ownership
dma_sync_sg_for_cpu()
CPU access
dma_sync_sg_for_device()
Device ownership

The sync APIs use the original SG entry count.

dma_sync_sg_for_cpu() does not pause or terminate DMA hardware. The DMA execution lifecycle must independently guarantee that the region is safe for CPU access.

struct sg_table

Subsystems frequently store SG mappings in:

struct sg_table

The important count relationship is:

orig_nents
    Original SG entry count

nents
    DMA-mapped segment count

dma_map_sgtable() maps using orig_nents and stores the mapped result in nents.

A controller driver can therefore pass:

sgt->sgl
sgt->nents

to dmaengine_prep_slave_sg() while the mapping owner retains orig_nents for later unmapping.

Notes

  • sgl must contain a valid DMA-mapped representation before transaction preparation.
  • sg_len is the mapped DMA segment count.
  • dmaengine_prep_slave_sg() does not perform DMA mapping.
  • Use sg_dma_address() and sg_dma_len() for DMA-visible segment information.
  • The original SG count and mapped DMA segment count are not interchangeable.
  • DMA mapping lifecycle operations use the original SG count.
  • DMA Engine transaction preparation uses the mapped count.
  • DMA mapping direction and DMA Engine transfer direction are different abstractions.
  • SG entries and DMA controller hardware descriptors are different abstraction layers.
  • One mapped segment may become multiple hardware descriptors or LLIs.
  • Some subsystem frameworks perform DMA mapping before the controller driver receives the transfer.
  • Determine which layer owns mapping and unmapping rather than assuming every DMA client driver calls dma_map_sg() directly.
  • Keep mapped memory valid until DMA access and relevant asynchronous completion activity can no longer access it.
  • DMA completion still does not necessarily imply peripheral-level completion.

See also:


dmaengine_prep_dma_cyclic()

Prepares a cyclic DMA transaction that repeatedly traverses a DMA buffer and generates period-based progress notifications.

Prototype

struct dma_async_tx_descriptor *
dmaengine_prep_dma_cyclic(struct dma_chan *chan,
                          dma_addr_t buf_addr,
                          size_t buf_len,
                          size_t period_len,
                          enum dma_transfer_direction dir,
                          unsigned long flags);

Parameters

Parameter Description
chan DMA channel used for the cyclic transaction.
buf_addr DMA address of the cyclic buffer.
buf_len Total length of the cyclic buffer.
period_len Length of each notification period.
dir DMA transfer direction.
flags DMA descriptor preparation flags.

Return Value

Returns a prepared struct dma_async_tx_descriptor on success.

Returns NULL if the DMA controller cannot prepare the requested cyclic transaction.

Description

dmaengine_prep_dma_cyclic() prepares one long-running DMA transaction that repeatedly traverses the supplied DMA buffer.

The buffer is divided into periods according to period_len.

For example:

buf_len    = 4096
period_len = 1024

┌──────────┬──────────┬──────────┬──────────┐
│    P0    │    P1    │    P2    │    P3    │
└──────────┴──────────┴──────────┴──────────┘
     ↑                                  │
     └──────────────────────────────────┘
                    wrap

The individual periods are not independent DMA transactions.

The descriptor is normally submitted once:

dmaengine_prep_dma_cyclic()
        |
        v
dmaengine_submit()
        |
        v
dma_async_issue_pending()
        |
        v
P0 -> P1 -> P2 -> P3
^                 |
|_________________|

The same cyclic descriptor and DMA cookie remain associated with the transaction while period callbacks occur.

A period callback reports progress within the cyclic transaction. It does not normally indicate normal transaction completion or retire the descriptor.

The actual cyclic execution mechanism is DMA-controller-specific. A controller may use a hardware descriptor ring, native circular mode, or another hardware-specific mechanism.

Typical Usage

struct dma_async_tx_descriptor *desc;
dma_cookie_t cookie;

desc = dmaengine_prep_dma_cyclic(chan,
                                 dma_addr,
                                 buf_len,
                                 period_len,
                                 DMA_DEV_TO_MEM,
                                 DMA_PREP_INTERRUPT);
if (!desc)
    return -EIO;

desc->callback = period_callback;
desc->callback_param = context;

cookie = dmaengine_submit(desc);
if (dma_submit_error(cookie))
    return dma_submit_error(cookie);

dma_async_issue_pending(chan);

Period Callback Semantics

For a cyclic transaction:

Period Boundary
        |
        v
Period Callback
        |
        v
Same Cyclic Transaction Continues

Therefore:

Period Callback
       !=
Transaction Completion

A period callback must not be interpreted as an implicit dma_cookie_complete() for the cyclic transaction.

Notes

  • The cyclic descriptor is normally prepared and submitted once.
  • period_len defines the notification periods within the cyclic buffer.
  • Periods are not assigned independent DMA cookies.
  • The DMA controller driver determines how cyclic execution and buffer wrap are implemented.
  • DMA hardware may continue into the next period before the client callback executes.
  • Client software must keep up with the cyclic producer/consumer stream.
  • Residue reporting and position accuracy depend on DMA controller capabilities.
  • Cyclic DMA normally continues until the client explicitly terminates the transaction.
  • Use the normal DMA Engine termination and synchronization APIs when stopping cyclic DMA.
  • Resources referenced by period callbacks must remain valid until the required synchronization boundary has been reached.

See also:


Transaction Submission and Execution

dmaengine_submit()

Submits a prepared DMA descriptor.

Prototype

dma_cookie_t dmaengine_submit(struct dma_async_tx_descriptor *desc);

Parameters

Parameter Description
desc Prepared DMA transaction descriptor to submit.

Return Value

Returns a dma_cookie_t identifying the submitted transaction.

A negative cookie indicates an error.

Description

dmaengine_submit() submits a descriptor that was previously prepared by one of the DMA Engine preparation APIs.

The function is a thin wrapper around the descriptor's tx_submit() callback:

dmaengine_submit(desc)
        |
        v
desc->tx_submit(desc)

The actual submission behavior is therefore provided by the descriptor implementation.

For DMA controller drivers using virt-dma, the descriptor's tx_submit() callback is commonly implemented by vchan_tx_submit().

The submission path typically assigns a DMA cookie and places the descriptor into the submitted queue.

Submission does not imply that the DMA hardware has started the transfer.

Example

struct dma_async_tx_descriptor *desc;
dma_cookie_t cookie;

cookie = dmaengine_submit(desc);
if (dma_submit_error(cookie))
    return -EIO;

Notes

  • The descriptor must already have been prepared before submission.
  • The returned cookie identifies the transaction for later status tracking.
  • Submission and execution are separate operations.
  • Call dma_async_issue_pending() when submitted transactions should become available for controller execution.

dma_async_issue_pending()

Makes pending DMA transactions available for execution.

Prototype

void dma_async_issue_pending(struct dma_chan *chan);

Parameters

Parameter Description
chan DMA channel containing submitted transactions.

Return Value

This function does not return a value.

Description

dma_async_issue_pending() tells the DMA Engine that previously submitted transactions on the channel may be issued to the DMA controller.

The framework dispatches the request through the controller's device_issue_pending() operation.

Conceptually:

dma_async_issue_pending(chan)
        |
        v
device_issue_pending(chan)
        |
        v
Controller Driver

For controllers using virt-dma, the controller driver commonly calls vchan_issue_pending() to move descriptors from the submitted list to the issued list.

An issued descriptor is eligible for controller scheduling, but it is not necessarily executing on the DMA hardware.

Example

cookie = dmaengine_submit(desc);
if (dma_submit_error(cookie))
    return -EIO;

dma_async_issue_pending(chan);

Notes

  • Call this API after submitting one or more descriptors.
  • Multiple descriptors may be submitted before a single call to dma_async_issue_pending().
  • Issued descriptors may still wait behind an active transaction.
  • dma_async_issue_pending() does not guarantee that a specific descriptor starts immediately.

The DMA Engine uses cookies to track the progress of asynchronous DMA transactions.

Cookie assignment and cookie completion are normally handled by the DMA controller implementation rather than directly by the client driver.

The basic lifecycle is:

Descriptor Submission
        |
        v
dma_cookie_assign()
        |
        v
cookie assigned
        |
        v
DMA execution
        |
        v
DMA completion
        |
        v
dma_cookie_complete()
        |
        v
cookie marked complete

Assigns the next DMA cookie to a transaction descriptor.

Prototype

dma_cookie_t dma_cookie_assign(struct dma_async_tx_descriptor *tx);

Parameters

Parameter Description
tx DMA transaction descriptor receiving the new cookie.

Return Value

Returns the newly assigned DMA cookie.

Description

dma_cookie_assign() advances the channel's cookie sequence and stores the new cookie in the descriptor.

Conceptually:

struct dma_chan
      |
      | next cookie
      v
struct dma_async_tx_descriptor
      |
      +--> tx->cookie

The cookie identifies the transaction within the channel's asynchronous transaction sequence.

For controllers using virt-dma, vchan_tx_submit() commonly calls dma_cookie_assign() as part of descriptor submission.

A simplified path is:

dmaengine_submit(desc)
        |
        v
desc->tx_submit(desc)
        |
        v
vchan_tx_submit()
        |
        v
dma_cookie_assign()

Notes

  • Cookie assignment occurs during descriptor submission.
  • Cookies are tracked per DMA channel.
  • The returned cookie can later be used to query transaction status.
  • Client drivers normally obtain the cookie from dmaengine_submit() rather than calling dma_cookie_assign() directly.

Marks a DMA transaction cookie as completed.

Prototype

void dma_cookie_complete(struct dma_async_tx_descriptor *tx);

Parameters

Parameter Description
tx DMA transaction descriptor that has completed.

Return Value

This function does not return a value.

Description

dma_cookie_complete() updates the channel's completed-cookie state when a DMA transaction finishes.

Conceptually:

DMA Hardware Completion
        |
        v
Controller completion handling
        |
        v
dma_cookie_complete(tx)
        |
        v
channel completed_cookie updated

For controllers using virt-dma, this operation is commonly part of vchan_cookie_complete().

The simplified relationship is:

vchan_cookie_complete(vd)
        |
        +--> dma_cookie_complete(&vd->tx)
        |
        +--> queue descriptor for completion processing
        |
        +--> tasklet_schedule()

Cookie completion and callback execution are separate events.

dma_cookie_complete() records the transaction as complete, while callback processing may execute later through the deferred completion path.

Notes

  • This helper is normally used by DMA controller implementations.
  • It records DMA transaction completion in the channel's cookie state.
  • Cookie completion does not mean that the client callback has already executed.
  • Controllers using virt-dma normally use the higher-level virt-dma completion helpers rather than implementing the entire completion path manually.

Transaction Status

DMA transaction status can be queried using the cookie returned during descriptor submission.

The client-facing entry point is dmaengine_tx_status().

The typical relationship is:

Client Driver
      |
      | dmaengine_tx_status()
      v
DMA Engine
      |
      | device_tx_status()
      v
DMA Controller Driver
      |
      +--> dma_cookie_status()
      |
      +--> controller-specific progress
      |
      v
enum dma_status
struct dma_tx_state

Generic cookie tracking determines whether a transaction has crossed the completion boundary.

Detailed progress information such as residue normally depends on the DMA controller driver and hardware capabilities.


dmaengine_tx_status()

Queries the status of a submitted DMA transaction.

Prototype

enum dma_status dmaengine_tx_status(struct dma_chan *chan,
                                    dma_cookie_t cookie,
                                    struct dma_tx_state *state);

Parameters

Parameter Description
chan DMA channel on which the transaction was submitted.
cookie Transaction cookie returned during descriptor submission.
state Optional transaction-state structure used to return additional progress information.

Return Value

Returns an enum dma_status describing the current transaction state.

Typical values include:

  • DMA_COMPLETE
  • DMA_IN_PROGRESS
  • DMA_PAUSED
  • DMA_ERROR

Description

dmaengine_tx_status() is the client-facing DMA Engine interface for querying the state of a previously submitted transaction.

The request is dispatched through the DMA controller's device_tx_status() operation.

Conceptually:

dmaengine_tx_status()
        |
        v
device_tx_status()
        |
        v
DMA Controller Driver

The controller driver commonly combines generic cookie tracking with controller-specific state or hardware progress information.

A transaction may already report DMA_COMPLETE after cookie completion even if its deferred client callback has not yet executed.

Example

struct dma_tx_state state;
enum dma_status status;

status = dmaengine_tx_status(chan, cookie, &state);

if (status == DMA_COMPLETE) {
    /* The transaction cookie has completed. */
} else if (status == DMA_IN_PROGRESS) {
    /* state.residue may contain progress information. */
}

Notes

  • The cookie should identify a valid transaction previously submitted on the channel.
  • Calling this API does not affect DMA hardware execution.
  • Residue accuracy depends on the DMA controller's reporting capability.
  • DMA_COMPLETE does not imply that a deferred completion callback has already executed.

device_tx_status()

Reports transaction status for a DMA controller channel.

Interface

device_tx_status() is an operation provided through struct dma_device.

Conceptually:

enum dma_status (*device_tx_status)(struct dma_chan *chan,
                                    dma_cookie_t cookie,
                                    struct dma_tx_state *txstate);

Description

The DMA controller driver implements device_tx_status() to translate generic cookie state and controller-specific progress into DMA Engine status information.

A common implementation pattern is:

device_tx_status()
        |
        +--> dma_cookie_status()
        |
        +--> inspect active descriptor
        |
        +--> inspect hardware progress
        |
        +--> update residue
        |
        v
return enum dma_status

Generic cookie tracking can determine whether the transaction is complete or still outstanding.

More detailed progress information requires controller-specific state.

Notes

  • This is a DMA controller operation rather than a normal client-driver API.
  • Implementations commonly use dma_cookie_status() as the generic completion check.
  • Residue reporting is controller-specific.

Determines generic transaction status from DMA cookie bookkeeping.

Prototype

enum dma_status dma_cookie_status(struct dma_chan *chan,
                                  dma_cookie_t cookie,
                                  struct dma_tx_state *state);

Parameters

Parameter Description
chan DMA channel containing the cookie bookkeeping state.
cookie Transaction cookie to query.
state Optional transaction-state structure to initialize with cookie information.

Return Value

Returns the generic cookie status for the transaction.

The result is normally:

  • DMA_COMPLETE
  • DMA_IN_PROGRESS

Description

dma_cookie_status() compares the requested transaction cookie against the channel's completed-cookie and last-used-cookie boundaries.

Conceptually:

requested cookie
      +
completed_cookie
      +
last used cookie
      |
      v
dma_async_is_complete()
      |
      v
DMA_COMPLETE
or
DMA_IN_PROGRESS

The helper performs generic transaction-order tracking.

It does not inspect DMA hardware and therefore cannot determine detailed transfer progress by itself.

Notes

  • This helper is commonly used by DMA controller device_tx_status() implementations.
  • Hardware-specific progress and residue must be added by the controller driver when supported.
  • Cookie completion and callback execution are independent.

dma_async_is_complete()

Determines whether a transaction cookie is outside the current outstanding cookie range.

Prototype

enum dma_status dma_async_is_complete(dma_cookie_t cookie,
                                      dma_cookie_t last_complete,
                                      dma_cookie_t last_used);

Parameters

Parameter Description
cookie Transaction cookie being queried.
last_complete Most recently completed cookie boundary.
last_used Most recently assigned cookie boundary.

Return Value

Returns:

  • DMA_COMPLETE if the cookie is considered completed.
  • DMA_IN_PROGRESS if the cookie lies within the current outstanding transaction range.

Description

DMA cookies form a finite sequence and eventually wrap.

dma_async_is_complete() handles both possible outstanding-window layouts.

Without wrap-around:

last_complete <= last_used

... COMPLETE ... | OUTSTANDING |
                 ^             ^
          last_complete     last_used

With wrap-around:

last_complete > last_used

          wrap
            |
            v

... last_complete | ... MAX ... MIN ... | last_used ...
                  \______________________/
                       OUTSTANDING

The helper determines completion from these relative boundaries without maintaining a separate wrap-generation counter.

Notes

  • The helper performs cookie-range comparison rather than cookie allocation.
  • It does not determine hardware progress.
  • It assumes that the supplied values represent meaningful DMA cookie state.

Transaction State

struct dma_tx_state

Carries additional transaction information returned by a DMA status query.

Important state includes the DMA residue.

Conceptually:

dmaengine_tx_status()
        |
        v
device_tx_status()
        |
        +--> enum dma_status
        |
        +--> struct dma_tx_state
                  |
                  +--> residue

The structure represents query-time state.

It is different from struct dmaengine_result, which represents completion-result information delivered through a result-aware callback.


DMA Residue

DMA residue represents the amount of transfer data that has not yet completed according to the progress information available to the DMA controller driver.

For example:

Requested transfer = 4096 bytes
Reported residue   = 1024 bytes

This indicates that 1024 bytes remain according to the controller's current reporting state.

Residue accuracy depends on the controller's supported granularity.

Possible granularity levels include:

Granularity Meaning
DMA_RESIDUE_GRANULARITY_DESCRIPTOR Progress is distinguishable only at descriptor level.
DMA_RESIDUE_GRANULARITY_SEGMENT Progress is distinguishable at transfer-segment boundaries.
DMA_RESIDUE_GRANULARITY_BURST Progress can be reported at burst-level granularity.

A status query observes current DMA state.

It does not stop, pause, or otherwise modify DMA hardware execution.


Completion Callback Interfaces

DMA Engine supports both basic and result-aware completion callbacks.

dma_async_tx_callback

Defines a basic DMA completion callback.

Conceptually:

void callback(void *param);

The callback notifies the client that a completion event has occurred.

It does not directly provide a transaction result or residue.


dma_async_tx_callback_result

Defines a result-aware DMA completion callback.

Conceptually:

void callback_result(void *param,
                     const struct dmaengine_result *result);

The callback receives a struct dmaengine_result containing completion-result information.

This allows the completion path to report information such as:

  • Successful completion
  • Read failure
  • Write failure
  • Aborted transfer
  • Completion residue

struct dmaengine_result

Carries result information supplied to a result-aware DMA callback.

The structure contains:

result
residue

The transaction result describes the outcome associated with the completion event.

Possible result values include:

DMA_TRANS_NOERROR
DMA_TRANS_READ_FAILED
DMA_TRANS_WRITE_FAILED
DMA_TRANS_ABORTED

struct dmaengine_result should not be confused with struct dma_tx_state.

struct dma_tx_state
    |
    +--> query-time transaction state

struct dmaengine_result
    |
    +--> completion-time result

The exact result and residue information available depends on the DMA controller implementation.


Completion Status vs Callback Execution

Cookie completion and callback execution are separate events.

A simplified completion path is:

DMA Hardware Complete
        |
        v
Controller completion handling
        |
        v
dma_cookie_complete()
        |
        v
Transaction status may report
DMA_COMPLETE
        |
        v
Deferred completion processing
        |
        v
Client callback

Therefore:

DMA_COMPLETE
    !=
callback already executed

For a detailed explanation of hardware completion, cookie completion, residue, callback processing, and virt-dma completion handling, see:


Cyclic DMA Callback Semantics

Cyclic DMA uses different callback semantics from normal one-shot transaction completion.

A cyclic period callback reports progress within an active long-running transaction:

Period Boundary
        |
        v
Period Callback
        |
        v
Cyclic Transaction Continues

The period callback does not normally advance the transaction through normal cookie completion.

For virt-dma-based controller drivers, this distinction can be represented by:

Cyclic Period Event
        |
        v
vchan_cyclic_callback()

Normal Transaction Completion
        |
        v
vchan_cookie_complete()

Therefore:

Callback Invocation
        !=
Normal Transaction Completion

The meaning of a callback depends on the transaction type and completion semantics.

For a detailed explanation, see:


Termination and Synchronization

DMA termination and synchronization are separate lifecycle operations.

Termination stops or retires outstanding DMA transactions, while synchronization ensures that remaining completion activity has reached a quiescent point before related client resources are released.

API Overview

API Purpose
dmaengine_terminate_async() Terminate outstanding DMA transactions without establishing a complete synchronization boundary.
dmaengine_synchronize() Synchronize remaining DMA completion activity after termination.
dmaengine_terminate_sync() Perform termination followed by synchronization.

dmaengine_terminate_async()

Terminates outstanding DMA transactions without synchronizing remaining completion activity.

Prototype

int dmaengine_terminate_async(struct dma_chan *chan);

Parameters

Parameter Description
chan DMA channel whose outstanding transactions should be terminated.

Return Value

Returns the result of the controller driver's termination operation.

A successful return indicates that the termination operation returned successfully.

It does not mean that deferred completion processing or callbacks have already quiesced.

Description

dmaengine_terminate_async() dispatches termination through the DMA controller driver.

Conceptually:

dmaengine_terminate_async()
        |
        v
device_terminate_all()
        |
        v
Controller-Specific Termination

The controller implementation may need to:

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

The exact behavior is controller-specific.

Notes

  • Termination is not equivalent to normal successful completion.
  • A successful return does not establish a safe client-resource cleanup boundary.
  • Deferred completion processing or callbacks may still be pending or running.
  • Use dmaengine_synchronize() when later cleanup requires old DMA completion activity to be quiescent.

dmaengine_synchronize()

Synchronizes DMA completion activity after termination.

Prototype

void dmaengine_synchronize(struct dma_chan *chan);

Parameters

Parameter Description
chan DMA channel whose terminated activity should be synchronized.

Return Value

This function does not return a value.

Description

dmaengine_synchronize() dispatches through the DMA controller driver's synchronization operation.

Conceptually:

dmaengine_synchronize()
        |
        v
device_synchronize()
        |
        v
Controller-Specific Synchronization
        |
        v
QUIESCENT

Depending on the controller implementation, synchronization may include:

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

The exact synchronization mechanism and ordering are provider-specific.

Notes

  • dmaengine_synchronize() does not initiate DMA termination.
  • It is used with the corresponding termination lifecycle before releasing resources referenced by old DMA activity.
  • Synchronization guarantees the required quiescent boundary; it does not guarantee that every previously scheduled callback executes.
  • Calling-context requirements depend on the synchronization semantics required by the DMA Engine API and provider implementation.

dmaengine_terminate_sync()

Terminates outstanding DMA transactions and synchronizes remaining completion activity.

Prototype

int dmaengine_terminate_sync(struct dma_chan *chan);

Parameters

Parameter Description
chan DMA channel whose outstanding transactions should be terminated and synchronized.

Return Value

Returns the termination result.

If termination succeeds, synchronization is performed before the function returns.

Description

dmaengine_terminate_sync() combines asynchronous termination and synchronization.

Conceptually:

dmaengine_terminate_sync()
        |
        +--> dmaengine_terminate_async()
        |
        +--> dmaengine_synchronize()
        |
        v
return

There is no separate device_terminate_sync() controller operation.

The client-facing synchronous API composes:

device_terminate_all()
        +
device_synchronize()

Notes

  • Use this API when termination and synchronization can be completed together in the current calling context.
  • After successful termination and synchronization, old DMA completion activity associated with the terminated work has reached the required quiescent boundary.
  • The client must still ensure that its own callbacks, workers, IRQ paths, or threads cannot submit new DMA work during shutdown.

device_terminate_all()

Terminates outstanding transactions for a DMA controller channel.

Interface

device_terminate_all() is an operation provided through struct dma_device.

Conceptually:

int (*device_terminate_all)(struct dma_chan *chan);

Description

The DMA controller driver implements this operation to perform controller-specific termination.

Responsibilities may include:

  • Stopping or aborting active DMA hardware.
  • Preventing queued descriptors from becoming active.
  • Retiring outstanding transactions.
  • Updating controller-specific channel state.
  • Moving descriptors into provider-specific termination state.

The exact descriptor handling is controller-specific.

Notes

  • This is a DMA controller operation rather than a normal DMA client API.
  • Termination does not by itself guarantee that callbacks or deferred completion activity have quiesced.
  • Controller-specific cookie bookkeeping during termination must not be generalized into generic DMA Engine behavior.

device_synchronize()

Synchronizes terminated DMA activity for a controller channel.

Interface

device_synchronize() is an operation provided through struct dma_device.

Conceptually:

void (*device_synchronize)(struct dma_chan *chan);

Description

The DMA controller driver implements this operation to establish the required quiescent boundary after termination.

Provider-specific synchronization may involve:

Hardware Quiescence
IRQ / Deferred Processing Quiescence
Callback Quiescence
Descriptor Reclamation

These operations do not imply a fixed generic ordering.

Notes

  • This is a DMA controller operation rather than a normal DMA client API.
  • The implementation depends on the controller's hardware, interrupt model, deferred completion mechanism, and descriptor-management architecture.
  • virt-dma-based controllers may use vchan_synchronize() as part of this operation.

virt-dma Termination Helpers

virt-dma provides reusable helpers that DMA controller drivers may use during termination and synchronization.

Relevant helpers include:

Helper Purpose
vchan_next_desc() Obtain the next descriptor from the virt-dma issued queue.
vchan_terminate_vdesc() Move a descriptor into virt-dma termination state.
vchan_get_all_descriptors() Collect descriptors managed by the virtual DMA channel.
vchan_synchronize() Synchronize virt-dma deferred completion activity and reclaim terminated descriptors.

A simplified virt-dma termination lifecycle is:

Outstanding Descriptor
        |
        v
Termination
        |
        v
desc_terminated
        |
        v
vchan_synchronize()
        |
        v
Descriptor Reclamation

virt-dma is an implementation helper and is not mandatory for every DMA controller driver.

For a detailed explanation of termination, synchronization, completion races, and client resource lifetime, see:


Notes

This page is a grouped DMA Engine API reference intended for lookup across the DMA transaction lifecycle.

It combines client-facing APIs with selected DMA controller operations and virt-dma helpers where those interfaces are useful for understanding submission, status, completion, termination, synchronization, and cyclic DMA behavior.

Controller-specific behavior may differ according to the DMA hardware and provider implementation.

For DMA client drivers, keep the following lifetimes conceptually separate:

DMA channel lifetime
DMA transaction lifetime
DMA mapping lifetime
buffer lifetime
peripheral completion lifetime

DMA completion does not automatically destroy the DMA mapping, and for peripheral transfers it does not necessarily mean that the peripheral protocol has completely finished.

A client must establish a DMA-safe boundary before unmapping or releasing backing memory.