Skip to content

Day98 - Linux DMA API

Date

2026-08-04


Objective

Understand how Linux prepares CPU memory for DMA-capable devices and why the Linux DMA Mapping API is required.

Implement a simulator that visualizes:

  • CPU virtual address
  • DMA address
  • Streaming DMA
  • Coherent DMA
  • DMA ownership
  • Cache coherency
  • Cache synchronization

What I Learned

Today I learned how Linux abstracts DMA-capable hardware through the DMA Mapping API.

Unlike MCU development, Linux drivers do not directly configure cache operations or perform address translation themselves. Instead, drivers use DMA Mapping APIs to prepare memory before programming the hardware DMA engine.

I also learned that the DMA Mapping API does not perform the DMA transfer itself.

Its responsibilities include:

  • Preparing CPU memory for DMA
  • Returning a DMA address
  • Managing DMA mapping lifetime
  • Handling platform-specific cache maintenance

The actual DMA transfer is still started by programming the DMA-capable device.


Key Concepts

DMA Address

A DMA-capable device accesses memory through a DMA address instead of a normal CPU virtual address.

CPU Virtual Address
Physical Address
DMA Address

Streaming DMA

Streaming DMA temporarily exposes an existing CPU buffer to a DMA-capable device.

Typical lifecycle:

CPU owns buffer
dma_map_single()
Device owns mapping
DMA transfer
dma_unmap_single()
CPU owns buffer

Coherent DMA

Coherent DMA allocates memory that is simultaneously visible to both the CPU and the device.

CPU
Shared DMA Buffer
Device

Unlike Streaming DMA, coherent DMA normally does not require explicit synchronization.


DMA Direction

DMA direction is always described from the DMA device's point of view.

Direction Typical Meaning
DMA_TO_DEVICE Device reads CPU-prepared data
DMA_FROM_DEVICE Device writes data for the CPU
DMA_BIDIRECTIONAL Both CPU and device modify the buffer

Cache Coherency

Streaming DMA may require cache synchronization.

CPU → Device:

CPU Cache
dma_sync_single_for_device()
Device-visible Memory

Device → CPU:

Device-visible Memory
dma_sync_single_for_cpu()
CPU Cache

Simulator

Implemented a DMA Mapping simulator supporting:

Streaming DMA

  • dma_map_single()
  • dma_unmap_single()
  • dma_mapping_error()

Coherent DMA

  • dma_alloc_coherent()
  • dma_free_coherent()

CPU / Device Access

  • dma_cpu_write()
  • dma_cpu_read()
  • dma_device_write()
  • dma_device_read()

Cache Synchronization

  • dma_sync_single_for_device()
  • dma_sync_single_for_cpu()

Mapping Manager

The simulator tracks:

  • CPU virtual address
  • DMA address
  • Mapping type
  • DMA direction
  • Mapping owner
  • CPU cache validity
  • CPU cache dirty state

Labs

Completed four simulator-based labs.

Lab1

DMA Mapping

Verified:

  • Basic mapping
  • Duplicate mapping rejection
  • Invalid parameters
  • Valid unmap
  • Invalid unmap

Lab2

Coherent DMA

Verified:

  • Coherent allocation
  • Multiple allocations
  • Invalid allocation
  • Invalid free

Lab3

Streaming DMA Lifecycle

Verified:

  • DMA_TO_DEVICE lifecycle
  • DMA_FROM_DEVICE lifecycle
  • Unmap then remap
  • Invalid DMA direction

Lab4

DMA Cache Coherency

Verified:

  • CPU → Device synchronization
  • Device → CPU synchronization
  • Coherent shared memory
  • Invalid synchronization requests

Takeaways

The Linux DMA Mapping API is fundamentally a memory management interface rather than a hardware DMA controller.

It prepares CPU memory for DMA-capable devices, manages mapping lifetime, and provides a portable abstraction for cache coherency across different architectures.

Understanding Streaming DMA, Coherent DMA, ownership transfer, and cache synchronization provides the foundation for studying Ethernet, USB, SPI, storage, multimedia, and other DMA-capable Linux drivers.


  • Linux DMA Mapping
  • Memory Barriers
  • ioremap()
  • MMIO Access APIs

Next

Study the Linux DMA Engine Framework and how DMA controllers are exposed through the kernel DMA Engine subsystem.