Linux内核设备驱动程序将DMA转换为内核空间

时间:2022-12-31 00:16:46

LDD3 (p:453) demos dma_map_single using a buffer passed in as a parameter.

LDD3(p:453)使用作为参数传入的缓冲区演示dma_map_single。

bus_addr = dma_map_single(&dev->pci_dev->dev, buffer, count, dev->dma_dir);

Q1: What/where does this buffer come from?

Q1:这个缓冲区来自哪里/哪里?

kmalloc?

kmalloc的?

Q2: Why does DMA-API-HOWTO.txt state I can use raw kmalloc to DMA into?

Q2:为什么DMA-API-HOWTO.txt状态我可以使用原始kmalloc进行DMA转换?

Form http://www.mjmwired.net/kernel/Documentation/DMA-API-HOWTO.txt

表格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:51如果您通过页面分配器kmalloc()获取了内存,那么您可以使用从这些例程返回的地址与该内存进行DMA。

L:74 you cannot take the return of a kmap() call and DMA to/from that.

L:74你不能接受kmap()调用和DMA的返回。

  1. So I can pass the address returned from kmalloc to my hardware device?
  2. 所以我可以将kmalloc返回的地址传递给我的硬件设备?
  3. Or should I run virt_to_bus on it first?
  4. 或者我应该先在它上面运行virt_to_bus吗?
  5. Or should I pass this into dma_map_single?
  6. 或者我应该将其传递给dma_map_single?

Q3: When the DMA transfer is complete, can I read the data in the kernel driver via the kmalloc address?

问题3:DMA传输完成后,我可以通过kmalloc地址读取内核驱动程序中的数据吗?

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

Q4: Whats the best way to get this to user-space?

问题4:将这个用户空间送到用户空间的最佳方式是什么?

  1. copy_to_user?
  2. copy_to_user?
  3. mmap the kmalloc memory?
  4. mmap kmalloc内存?
  5. others?
  6. 其他?

1 个解决方案

#1


16  

  1. kmalloc is indeed one source to get the buffer. Another can be alloc_page with the GFP_DMA flag.

    kmalloc确实是获取缓冲区的一个来源。另一个可以是带有GFP_DMA标志的alloc_page。

  2. 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)

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

  3. Correct, just make sure to follow cache coherency guidelines as the DMA guide explains.

    正确,只需确保遵循缓存一致性指南,如DMA指南所述。

  4. 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)

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

Good luck!

祝你好运!

#1


16  

  1. kmalloc is indeed one source to get the buffer. Another can be alloc_page with the GFP_DMA flag.

    kmalloc确实是获取缓冲区的一个来源。另一个可以是带有GFP_DMA标志的alloc_page。

  2. 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)

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

  3. Correct, just make sure to follow cache coherency guidelines as the DMA guide explains.

    正确,只需确保遵循缓存一致性指南,如DMA指南所述。

  4. 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)

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

Good luck!

祝你好运!