The Linux kernel documentation (Dynamic DMA mapping Guide, DMA-API-HOWTO, and the DMA API reference) gives the sequence for streaming mappings. On a non-coherent platform each sync call performs the clean or invalidate defined in Part 3. On a coherent platform the same calls do no cache maintenance, but the sequence and ownership rule still apply.
Ownership rule: between dma_sync_*_for_device and dma_sync_*_for_cpu (or unmap), the buffer belongs to the device and the CPU must not touch it.
Step | To the device (DMA_TO_DEVICE) | Effect in the X example |
|---|---|---|
1 | CPU writes the buffer | C0 M / 1, memory = 0 |
2 |
| memory = 1 before the doorbell |
3 | MMIO doorbell with | D starts and reads 1 |
Step | From the device (DMA_FROM_DEVICE) | Effect in the X example |
|---|---|---|
1 |
| No dirty CPU copy of X left to be written back over D's data |
2 | Device writes | memory = 2, CPU does not touch the buffer |
3 | Completion: interrupt or status read | D has finished writing X |
4 |
| C0 invalidated, so the CPU load misses and reads 2 |
5 | CPU reads | CPU sees 2 |
Maintenance works on whole 64-byte lines. Suppose a CPU variable shares X's line with a DMA_FROM_DEVICE buffer. The invalidate after completion discards any CPU update to that variable, and a clean, or the eviction of a dirty line, writes the CPU's stale copy of X back over D's data. So DMA buffers must be cache-line aligned and padded to whole lines: no CPU data may share their lines.
For coherent descriptor memory no cache maintenance is needed, but coherence does not order the doorbell. The producer writes the descriptor fields, then dma_wmb(), then sets the valid bit, then rings the doorbell with writel(), which waits for the earlier memory writes before the MMIO store. On completion the consumer reads the status, then dma_rmb(), then reads the payload, so the payload is not read before the status says it is ready (Linux kernel memory barriers document). A fence is not a cache flush, and cache maintenance is not a device-completion wait: see the fence lesson.
The X example separates failures. If C0 produced 1 but a non-coherent D reads 0, the to-device sync was missing. If D produced 2 but the CPU reads an old 1, the for-CPU sync after completion was missing. If D's 2 was overwritten by 1 later, the pre-sync before the device wrote, or the line alignment, was missing. If the DMA address points elsewhere, no sync or fence repairs that bug.
No. Maintenance reconciles data. The device's completion event (interrupt or status read) establishes that its writes are complete.
The invalidate after completion discards CPU updates to the counter, or a clean or dirty eviction of the line writes the CPU's stale copy over D's data. Align and pad DMA buffers to whole cache lines.