There are certain functions for processing buffers for an interface with a DMA controller. These functions take care not only of address translation, but also of the coherence of the cache with memory, such as flash cache (write data to memory before sending) and cache invalid (invalidate cache before receiving).
(1) To allocate a buffer, get both the virtual address and the physical address:
void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag)
the return value of the function is the virtual address of the allocated buffer, and the dma_handle pointer stores the physical address of the allocated buffer.
(2) To transfer one buffer allocated to a device:
dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, enum dma_data_direction dir)
The returned value is the physical address of the buffer, and the dir parameter is DMA_TO_DEVICE, ptr is the virtual address of the buffer;
(3) To receive one buffer from a device:
void dma_unmap_single(struct device *dev, dma_addr_t addr, size_t size, enum dma_data_direction dir)
The dir parameter is DMA_FROM_DEVICE.
Note: To use the three functions related to dma, you must register the device on one specific bus that has dma_map_ops, or these three functions cannot be used.