Wednesday, 16 March 2016

Linux DMA Api's and details

Following documents gives many details of DMA-APIs used in Linux : 

Linux Documentation :

Online tutorials :,0

Intel VT-D  spec explaining IOMMU, IOTLB, DMA maps etc.

dma_map_ops for intel platform

struct dma_map_ops intel_dma_ops = {
.alloc = intel_alloc_coherent,
.free = intel_free_coherent,
.map_sg = intel_map_sg,
.unmap_sg = intel_unmap_sg,
.map_page = intel_map_page,
.unmap_page = intel_unmap_page,
.mapping_error = intel_mapping_error,


IOMMU hardware translates bus addresses(as seen by device) to physical addresses(RAM address).

dma_map_single(), takes the CPU virtual address, sets up any required IOMMU mapping and returns the bus address.

dma_set_mask_and_coherent(struct device *dev, u64 mask); -- Checks if device  can address 32bits, 64 bits or 24 bits etc.

Consistent DMA mappings :
1. returns two values: the virtual address which you can use to access it from the CPU and dma_handle which you pass to the card.
2. The CPU virtual address returned is in multiples of pages.
vaddr = (void *)__get_free_pages(flags, order);
3. Can use map_single to generate the dma_handle(bus address as seen by device)
*dma_handle = __intel_map_single(dev, virt_to_bus(vaddr), size,


These work much like a struct kmem_cache allocating small DMA-coherent memory regions

Streaming DMA mapping : 
dma_map_single(struct device *dev, void *cpu_addr, size_t size,
     enum dma_data_direction direction)
Maps a piece of processor virtual memory so it can be accessed by the device and returns the bus address of the memory.
dma_map_page(struct device *dev, struct page *page,
   unsigned long offset, size_t size,
   enum dma_data_direction direction)
dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,

        enum dma_data_direction direction)

dma_map_sg(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction direction)

Returns: the number of bus address segments mapped (this may be shorter than <nents> passed in if some elements of the scatter/gather list are physically or virtually adjacent and an IOMMU maps them with a  single entry).

virt_to_bus() and bus_to_virt() functions have been
superseded by the functionality provided by the PCI DMA interface

No comments:

Post a Comment