Day102 — DMA Descriptor Submission and Completion¶
Goal¶
Understand how a prepared DMA descriptor progresses from submission to hardware execution and completion.
The focus is the complete execution path of one asynchronous DMA transaction:
What I Learned¶
Descriptor Submission¶
A prepared descriptor is submitted with:
dmaengine_submit() dispatches through the descriptor's tx_submit() callback.
For controllers using virt-dma, this callback is commonly implemented by vchan_tx_submit().
The submission path assigns a DMA cookie and places the descriptor into the submitted state.
The important distinction is:
Submission does not start DMA hardware execution.
DMA Cookie Assignment¶
dma_cookie_assign() assigns a transaction cookie during descriptor submission.
The cookie identifies the asynchronous transaction and allows its completion state to be tracked later.
The client driver normally receives the cookie from dmaengine_submit() rather than calling dma_cookie_assign() directly.
Issuing Pending Descriptors¶
After one or more descriptors have been submitted, the client driver calls:
The framework dispatches through the controller's device_issue_pending() operation.
For controllers using virt-dma, vchan_issue_pending() moves descriptors from:
An issued descriptor is available for controller scheduling.
However:
Issued does not mean running.
A descriptor in desc_issued may still wait while another transaction is active on the DMA channel.
Pending and Active Work¶
virt-dma manages generic descriptor lists such as:
desc_allocateddesc_submitteddesc_issueddesc_completed
The active descriptor is typically maintained by controller-specific state rather than a generic virt-dma active list.
This gives the following ownership model:
vchan_next_desc() Only Peeks¶
One important source-code detail was that vchan_next_desc() returns the descriptor at the head of desc_issued, but does not remove it from the list.
Conceptually:
means:
The controller driver removes the descriptor when it actually consumes the transaction, commonly with:
Therefore:
vchan_next_desc()selects by inspection; controller-specific scheduling logic performs the actual ownership transition.
DMA Completion¶
When the hardware finishes a transaction, the controller handles the completion interrupt.
For a virt-dma based controller, the completion path commonly reaches:
This path performs several logically separate operations:
Hardware completion
↓
dma_cookie_complete()
↓
Descriptor completion state
↓
tasklet_schedule()
↓
Deferred completion processing
↓
Client callback
Hardware completion and callback execution are therefore not the same event.
Cookie Completion¶
dma_cookie_complete() records that the transaction has completed.
The important distinction is:
The DMA Engine can record the transaction as complete before the client callback runs.
tasklet_schedule() and Callback Execution¶
vchan_cookie_complete() schedules deferred completion processing with:
A tasklet is not equivalent to an RTOS task.
Calling tasklet_schedule() does not immediately execute the callback or cause a priority-based RTOS-style task switch.
Instead, it requests deferred execution through the kernel's tasklet/softirq mechanism.
Locking During Completion¶
vchan_cookie_complete() expects the virtual channel lock to already be held.
The lock assertion verifies this calling contract; the function does not release the lock itself.
Conceptually:
Controller IRQ handler
|
v
spin_lock(&vc->lock)
|
v
vchan_cookie_complete()
|
v
spin_unlock(&vc->lock)
The callback itself is deferred and executes outside the controller's original locked completion section.
A useful distinction is:
Scheduling deferred callback processing while holding the lock is not the same as executing the callback while holding the lock.
The Next DMA Transaction Can Start Before the Callback¶
Descriptor completion processing does not necessarily block hardware scheduling.
For two descriptors A and B, a valid ordering is:
Descriptor A running
↓
A completes
↓
Cookie A complete
↓
Callback A scheduled
↓
Descriptor B selected
↓
Descriptor B running
↓
Callback A executes
Therefore:
Descriptor B may already be running before Descriptor A's callback executes.
This separates DMA hardware scheduling from software completion notification.
Complete Mental Model¶
A DMA transaction crosses three major responsibility domains:
Client Driver
|
| prepare / submit / issue
v
DMA Engine + Controller Driver
|
| queue / schedule / complete
v
DMA Hardware
|
| execute transfer
v
Controller Driver + DMA Engine
|
| completion processing
v
Client Callback
The responsibilities can be summarized as:
- The DMA Engine manages the transaction abstraction and common state.
- The Controller Driver schedules transactions and manages hardware-specific active state.
- The DMA Controller executes the actual transfer.
- Completion processing records transaction completion and eventually notifies the client.
Key Takeaways¶
dmaengine_submit()submits a prepared descriptor but does not start the hardware.tx_submit()provides the descriptor-specific submission implementation.dma_cookie_assign()assigns the transaction cookie during submission.dma_async_issue_pending()makes submitted descriptors available for controller scheduling.- Issued descriptors may still wait before becoming active.
vchan_next_desc()only peeks at the next issued descriptor.- The Controller Driver removes a descriptor from
desc_issuedwhen it consumes it. - Active descriptor state is normally controller-specific.
dma_cookie_complete()records transaction completion independently from callback execution.tasklet_schedule()requests deferred kernel execution; it is not an RTOS-style task switch.- Callback execution occurs outside the controller's original locked completion section.
- The next DMA transaction may start before the previous transaction's callback executes.