Allocate physical memory buffer for ARM64 Linux Device Driver (without DMA support)
Hi,
I have to implement an ARM64 Linux driver for a device that needs to work with physical memory buffers and that doesn't support DMA (nor IOMMU).
My first attempt was to allocate the buffers with kmalloc, use the returned vaddr virtual address in the driver and send the paddr physical address obtained after a virt_to_phys(vaddr) translation to the device. I understand that (in general) this is not be the best approach, since the device might only know its bus-specific addresses. But my problem is that the paddr address returned by
virt_to_phys(vaddr) isn't the same as the one listed in the PageTable for vaddr, so the device couldn't use it either (the virt_to_phys value looks like a shifted version of the real physical
address).
What worked for me was using the DMA mapping API (e.g. dma_alloc_coherent), but I'm not sure if this is the best approach, since the device module doesn't support DMA. The same question for dma_map_single function for temporary allocations.
Another option would be to pre-allocate a memory range (e.g. using a reserved-memory node in the device tree file) and ioremap it in the driver, but I'm not sure if that's OK either. Some of the buffers are only needed temporary (while the device is processing a command) and their size is variable (could get quite large). So, in this case, a
dynamic allocation might be better.
Any idea what would be the best memory management approach (practice) for this case? Also, why would virt_to_phys called over a kmalloc address not return the correct physical address?
Any help is appreciated.
|