0
votes

I'm writing a PCI device driver and i need to allocate some memory for DMA, I'm using this function:

void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, int flag);

I pass dma_handle to the device.

The return value of this function is a virtual address i can use in the kernel, the thing is i don't want to save this address for each memory allocation im doing.

Is there a way to translate the physical address dma_handle to an address i can use in the kernel? something like one of these functions/macros:

virt_to_page(kaddr)
page_to_pfn(page)

is there a phy_to_kvirt macro/function or any other way to translate a physical address to kernel virtual address?

thanks

1

1 Answers

5
votes

No, there isn't, and dma_handle isn't just any physical address. It is a physical address from the point of view of the specific device. Different devices on different buses may have entirely different views of the main memory. In addition to that, the returned virtual address may be a dynamically mapped page instead of having a fixed relation with physical mapping of main memory.

There may be enough information in kernel structures to piece the information together on certain buses and architectures but no guarantees and don't expect it to be fast – the kernel's own dma_free_coherent() requires you to supply everything, virtual address, device and dma_handle to do its work, because that is the only way it can work universally across architectures and buses.

Just to reiterate: A dma_handle is meaningless on its own. Multiple devices could have the exact same dma_handle that still refers to different memory locations.