Linux内核设备驱动程序以DMA方式进入内核空间
LDD3 (p:453) 演示 dma_map_single
使用作为参数传入的缓冲区。
bus_addr = dma_map_single(&dev->pci_dev->dev, buffer, count, dev->dma_dir);
Q1:这个缓冲区来自什么/哪里?
kmalloc?
Q2:为什么 DMA-API-HOWTO.txt 声明我可以使用原始 kmalloc
进行 DMA?
表格 http://www.mjmwired.net/kernel/Documentation/DMA- API-HOWTO.txt
L:51 如果您通过页面分配器 kmalloc() 获取内存,那么您可以使用从这些例程返回的地址与该内存进行 DMA 传输。
L:74 您无法从中获取 kmap() 调用和 DMA 的返回值。
- 那么我可以将从
kmalloc
返回的地址传递到我的硬件设备吗? - 或者我应该先运行
virt_to_bus
? - 或者我应该将其传递给
dma_map_single
?
Q3:当DMA传输完成后,我可以通过kmalloc
地址读取内核驱动中的数据吗?
addr = kmalloc(...);
...
printk("test result : 0x%08x\n", addr[0]);
Q4:将其传递到用户空间的最佳方法是什么?
复制到_用户
?- mmap kmalloc 内存?
- 其他的?
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, count, 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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
kmalloc 确实是获取缓冲区的来源之一。另一个可以是带有 GFP_DMA 标志的 alloc_page。
意思是kmalloc返回的内存保证在物理内存中是连续的,而不仅仅是虚拟内存,因此您可以将该指针的总线地址提供给您的硬件。您确实需要在返回的地址上使用 dma_map_single(),根据具体平台,该地址可能不再是 virt_to_bus 的包装器,或者可能执行更多操作(设置 IOMMU 或 GART 表)
正确,只需确保遵循缓存即可正如 DMA 指南所解释的一致性准则。
copy_to_user 可以正常工作,并且是最简单的答案。根据您的具体情况,这可能就足够了,或者您可能需要性能更好的东西。您通常无法将 kmalloced 地址映射到用户空间,但您可以 DMA 到用户提供的地址(适用一些注意事项)或分配用户页面(alloc_page 与 GFP_USER)
祝您好运!
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!