Linux kernel device driver to DMA into kernel space
LDD3 (p:453) demos dma_map_single
using a buffer passed in as a parameter.
bus_addr = dma_map_single(&dev->pci_dev->dev, buffer, co开发者_运维问答unt, dev->dma_dir);
Q1: What/where does this buffer come from?
kmalloc
?
Q2: Why does DMA-API-HOWTO.txt state I can use raw kmalloc
to DMA into?
Form http://www.mjmwired.net/kernel/Documentation/DMA-API-HOWTO.txt
L:51 If you acquired your memory via the page allocator kmalloc() then you may DMA to/from that memory using the addresses returned from those routines.
L:74 you cannot take the return of a kmap() call and DMA to/from that.
- So I can pass the address returned from
kmalloc
to my hardware device? - Or should I run
virt_to_bus
on it first? - Or should I pass this into
dma_map_single
?
Q3: When the DMA transfer is complete, can I read the data in the kernel driver via the kmalloc
address?
addr = kmalloc(...);
...
printk("test result : 0x%08x\n", addr[0]);
Q4: Whats the best way to get this to user-space?
copy_to_user
?- mmap the kmalloc memory?
- others?
kmalloc is indeed one source to get the buffer. Another can be alloc_page with the GFP_DMA flag.
The meaning is that the memory that kmalloc returns is guaranteed to be contiguous in physical memory, not just virtual memory, so you can give the bus address of that pointer to your hardware. You do need to use dma_map_single() on the address returned which depending on exact platform might be no more then wrapper around virt_to_bus or might do more then do (set up IOMMU or GART tables)
Correct, just make sure to follow cache coherency guidelines as the DMA guide explains.
copy_to_user will work fine and is the easiest answer. Depending on your specific case it might be enough or you might need something with better performance. You cannot normaly map kmalloced addresses to user space, but you can DMA into user provided address (some caveats apply) or allocate user pages (alloc_page with GFP_USER)
Good luck!
精彩评论