【问题标题】:Linux kernel device driver to DMA into kernel spaceLinux 内核设备驱动程序以 DMA 方式进入内核空间
【发布时间】:2011-04-06 09:39:52
【问题描述】:

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 的返回。

  1. 那么我可以将kmalloc返回的地址传递给我的硬件设备吗?
  2. 还是我应该先运行virt_to_bus?
  3. 或者我应该把它传递给dma_map_single?

Q3:DMA传输完成后,可以通过kmalloc地址读取内核驱动中的数据吗?

addr = kmalloc(...);
...
printk("test result : 0x%08x\n", addr[0]);

Q4:将它放到用户空间的最佳方式是什么?

  1. copy_to_user?
  2. 映射 kmalloc 内存?
  3. 其他人?

【问题讨论】:

    标签: linux linux-kernel linux-device-driver dma


    【解决方案1】:
    1. kmalloc 确实是获取缓冲区的一种来源。另一个可以是带有 GFP_DMA 标志的 alloc_page。

    2. 意思是kmalloc返回的内存保证在物理内存中是连续的,而不仅仅是虚拟内存,所以你可以把那个指针的总线地址给你的硬件。您确实需要在返回的地址上使用 dma_map_single(),这取决于确切的平台,可能不再是 virt_to_bus 的包装器,或者可能做的更多(设置 IOMMU 或 GART 表)

    3. 正确,只要确保遵循 DMA 指南中解释的缓存一致性准则即可。

    4. copy_to_user 可以正常工作,是最简单的答案。根据您的具体情况,这可能就足够了,或者您可能需要性能更好的东西。您不能正常地将 kmalloced 地址映射到用户空间,但您可以 DMA 到用户提供的地址(一些注意事项适用)或分配用户页面(alloc_page 和 GFP_USER)

    祝你好运!

    【讨论】:

    • 我将标记为 1 和 2 的第二组点的 MarkDown 自动编号更改为 3 和 4 的编辑被拒绝(我认为)
    • 是不是“dma_map_single”只是简单地将虚拟地址转换为物理地址?
    猜你喜欢
    • 2011-07-29
    • 2012-03-12
    • 2015-06-01
    • 2017-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多