I'm porting a large code base to a Linux kernel device driver. The ASIC uses a huge number of DMA channels.
I kmalloc memory with GFP_KERNEL|GFP_DMA
. Before starting the DMA, I use dma_map_single to get the hardware (physical) memory address to feed to the hardware. (Also does a flush/invalidate the memory from dcache?) I sometimes need CPU access to the data once DMA is complete, but not often. Before I access the data via code, I do a dma_unmap_single to avoid cache coherency issues.
In the cases where I do not ever need CPU access, do I still need to call dma_unmap_single
? Should I dma_unmap_single
every pointer I dma_map_single
? Does dma_map_single
consume a resource (e.g., table entry) that dma_unmap_single
will release?
The DMA-API.txt isn't clear on good DMA memory hygiene.
Thanks!
There is no way to disable SWIOTLB in the kernel configuration. Since kernel v4. 10, the swiotlb=noforce kernel parameter turns off SWIOTLB and any attempt to use it along with DMA mappings, and the memory allocation is reduced to minimum (and no allocation at all from kernel v5.
Direct memory access, or DMA, is the advanced topic that completes our overview of memory issues. DMA is the hardware mechanism that allows peripheral components to transfer their I/O data directly to and from main memory without the need for the system processor to be involved in the transfer.
A DMA buffer can be allocated in two ways: Contiguous Buffer: A contiguous block of memory is allocated. Scatter/Gather: The allocated buffer can be fragmented in the physical memory and does not need to be allocated contiguously.
dma_sync_single_for_cpu() gives ownership of the DMA buffer back to the processor. After that call, driver code can read or modify the buffer, but the device should not touch it. A call to dma_sync_single_for_device() is required to allow the device to access the buffer again.
With dma_map_single
you map the memory for DMA transfer. You get the physical pointer to the memory, so the device can DMA to that address.
With dma_unmap_single
you unmap the memory mapped above. You should do this when your transfers are over.
You can map a memory region, and use it for multiple DMA transfers and then you unmap when the job is done. Each time you want to access the DMA memory you must synchronize it. If the device is going to access the memory, you should do dma_sync_single_for_device
; it the host is going to access the memory, you should do dma_sync_single_for_cpu
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With