The Linux DMA mapping API exists to solve two problems for driver authors: translating a CPU buffer into a bus address the device can use, and inserting the cache maintenance operations needed on non-coherent architectures. Coherent mappings (dma_alloc_coherent) are for small, long-lived control structures accessed by both CPU and device without explicit syncing, while streaming mappings (dma_map_single, dma_map_page, dma_map_sg) are for bulk data mapped just before a transfer and unmapped after, with explicit sync calls if the CPU touches the buffer in between. In the Linux 7.x source, every mapping with no custom DMA ops and no IOMMU takes the dma-direct fast path through dma_map_phys(), and CONFIG_DMA_API_DEBUG can validate that a driver's map and unmap calls are used correctly.

If you write drivers for embedded Linux, the DMA mapping API is one of the interfaces you cannot avoid for long. The moment a device moves data into or out of memory on its own, without the CPU copying each byte, your driver has to tell the kernel how that memory should be prepared. Get it wrong and the symptoms are some of the hardest to debug in kernel work: data that is correct on a desktop x86 board but corrupted on an ARM target, or a buffer that reads back stale values only under load. This Deep Dive comes in two parts. First it covers the concepts and rules every driver author needs: coherent versus streaming mappings, the DMA mask, directions, and syncing. Then it goes one layer down and traces the kernel source that implements them, from the dispatch in kernel/dma/mapping.c to the arm64 cache hooks and the CONFIG_DMA_API_DEBUG facility. The source shown is from Linux 7.1, whose series reworked the DMA core to be physical-address based.