networkinglinux-kernellinux-device-driverdma

Streaming DMA vs consistent DMA


I have followed the DMA API https://www.kernel.org/doc/Documentation/DMA-API-HOWTO.txt and I understand that there are 2 types of methods for DMA:

  1. Consistent DMA mappings - for example dma_alloc_coherent()
  2. Streaming DMA - for example dma_map_single()

In "Linux Device driver" book states that method (2) is preferred:

The kernel developers recommend the use of streaming mappings over coherent mappings whenever possible. There are two reasons for this recommendation. The first is that, on systems that support mapping registers, each DMA mapping uses one or more of them on the bus. Coherent mappings, which have a long lifetime, can monopolize these registers for a long time, even when they are not being used. The other reason is that, on some hardware, streaming mappings can be optimized in ways that are not available to coherent mappings.

Yet, I see that in ethernet adapter drivers, some are using method (1) while others are using method (2). So, my question is:

Is there any reason/advantage for using method (1) if we already have a buffer (for example in ethernet driver the API already gets skb buffer and just need to transmit it).


Solution

  • It's not a choice. If you have a fixed ring buffer in memory, such as the I/O completion ring, where both the device and the CPU need to access in overlapping fashion, then it needs to be marked as non-cacheable. So it is mapped with dma_alloc_coherent().

    The same device may also be writing or reading buffers not overlapping with the CPU, so the CPU flushes the buffers from cache (synchronizes) and maps them for DMA using dma_map_single(). The CPU unmaps when done so it can use them again.

    If you look though the code, many network drivers are using both calls for the two different purposes.