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.
Header¶
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¶
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:
For DMA_DEV_TO_MEM, the peripheral is normally described by the src_* fields:
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_addris normally used when the peripheral is the DMA source.dst_addris 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. |
Cookie Management Helpers¶
| 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_chanobjects - 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_addranddst_addrfor peripheral endpoints.src_addr_widthanddst_addr_widthfor peripheral transfer width.src_maxburstanddst_maxburstfor requested burst behavior.device_fcfor 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¶
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_DEFERif the DMA provider has not completed probe.
dma_release_channel()¶
Releases a DMA channel previously obtained by dma_request_chan().
Prototype¶
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¶
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:
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.
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¶
bufis 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_DEVICEbelong to the DMA mapping API.DMA_MEM_TO_DEV/DMA_DEV_TO_MEMbelong to DMA Engine.- Configure the completion callback after descriptor preparation succeeds and before submission.
- Check the cookie returned by
dmaengine_submit()withdma_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_slave_config()dmaengine_prep_slave_sg()dmaengine_submit()dma_async_issue_pending()dmaengine_terminate_sync()- DMA Slave Transfer
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:
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:
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:
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:
For DMA_DEV_TO_MEM:
The DMA controller provider combines:
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.
A provider may split one mapped segment because of:
- Maximum DMA block size
- Address alignment
- Transfer width
- Burst restrictions
- Controller-specific transfer limits
Therefore:
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:
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.
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:
The important count relationship is:
dma_map_sgtable() maps using orig_nents and stores the mapped result in nents.
A controller driver can therefore pass:
to dmaengine_prep_slave_sg() while the mapping owner retains orig_nents for later unmapping.
Notes¶
sglmust contain a valid DMA-mapped representation before transaction preparation.sg_lenis the mapped DMA segment count.dmaengine_prep_slave_sg()does not perform DMA mapping.- Use
sg_dma_address()andsg_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_slave_single()dmaengine_slave_config()dmaengine_submit()dma_async_issue_pending()dmaengine_terminate_sync()- DMA Slave Transfer
- DMA Scatter-Gather Transfer
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:
Therefore:
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_lendefines 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:
- Cyclic DMA
dmaengine_submit()dma_async_issue_pending()dmaengine_tx_status()dmaengine_terminate_async()dmaengine_synchronize()
Transaction Submission and Execution¶
dmaengine_submit()¶
Submits a prepared DMA descriptor.
Prototype¶
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:
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¶
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:
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.
Cookie Management Helpers¶
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
dma_cookie_assign()¶
Assigns the next DMA cookie to a transaction descriptor.
Prototype¶
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:
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:
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 callingdma_cookie_assign()directly.
dma_cookie_complete()¶
Marks a DMA transaction cookie as completed.
Prototype¶
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-dmanormally use the higher-levelvirt-dmacompletion 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_COMPLETEDMA_IN_PROGRESSDMA_PAUSEDDMA_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:
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_COMPLETEdoes 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.
dma_cookie_status()¶
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_COMPLETEDMA_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_COMPLETEif the cookie is considered completed.DMA_IN_PROGRESSif 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:
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:
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:
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:
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:
The transaction result describes the outcome associated with the completion event.
Possible result values include:
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:
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:
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:
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¶
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:
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¶
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¶
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:
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:
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:
Description¶
The DMA controller driver implements this operation to establish the required quiescent boundary after termination.
Provider-specific synchronization may involve:
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.
Related Topics¶
- Linux DMA Engine Framework
- DMA Controller Driver and DMA Channel
- DMA Descriptor
- DMA Completion and Transaction Status
- DMA Termination and Synchronization
- Cyclic DMA
- DMA Slave Configuration
- DMA Slave Transfer
- DMA Scatter-Gather Transfer
- DMA Client Driver Architecture