Search code examples
linux-kernellinux-device-driverdma

DMA transaction requires copying into buffer every time?


It might be a silly question, but I haven't got it so far about DMA.
When doing memory to memory DMAing, it requires to allocate DMA buffer (for example with dma_alloc_coherent()), then for each transfer we need to copy the buffer to the allocated memory (source buffer) and then trigger DMA transaction.

So, if it requires additional memcpy() for each transaction, what's the benefit of using DMA?

Steps for copying source to destination - without DMA:

  1. copy buffer (memcpy()) from source to destination

Steps for copying source to destination - with DMA:

  1. copy buffer (memcpy()) from source to DMA buffer
  2. trigger DMA transaction (which shall copy the buffer eventually to destination buffer)

An example of this problem is with Ethernet driver, which need to copy from the recieved sk_buf into physical address of FPGA. In this case it shall requires copying the sk_buf into the DMA source buffer (from dma_alloc_coherent()) first.


Solution

  • If you can use dma_map_single() with the sk_buf pointer, then you do not have to copy it into a buffer allocated with dma_alloc_coherent(). There are many examples of this in network device drivers.

    int dma_len = skb->len;
    dma_addr_t dma_addr = dma_map_single(dev, skb->data, skb->len, DMA_TO_DEVICE);
    
    // error checking code here
    // then send the dma_addr to the drvice
    // when it is done, unmap it
    dma_unmap_single(dev, dma_addr, dma_len, DMA_TO_DEVICE);
    

    See the DMA Mapping API documentation for more details.