Linux PCIe DMA 驱动程序 (Xilinx XDMA)

标签 linux driver fpga xilinx pci-e

我目前正在使用 Xilinx XDMA 驱动程序(请参阅此处的源代码:XDMA Source),并试图让它运行(在您询问之前:我已经联系了我的技术支持联系人和 Xilinx 论坛到处都是有同样问题的人)。但是,我可能在 Xilinx 的代码中发现了一个障碍,这对我来说可能是一个交易破坏者。我希望有一些我没有考虑的事情。

首先,驱动程序有两种主要模式,AXI-Memory Mapped (AXI-MM) 和 AXI-Streaming (AXI-ST)。对于我的特定应用,我需要 AXI-ST,因为数据将持续从设备中流出。

驱动程序是为利用分散-聚集列表而编写的。在 AXI-MM 模式下,这是有效的,因为读取是相当随机的事件(即,没有数据流出设备,用户空间应用程序只是在需要时请求数据)。因此,建立 DMA 传输,传输数据,然后拆除传输。这是 get_user_pages()pci_map_sg()pci_unmap_sg() 的组合。

对于 AXI-ST,事情变得很奇怪,源代码远非正统。驱动程序分配一个循环缓冲区,数据将源源不断地流入其中。这个缓冲区的大小通常有点大(我的设置为 32MB 左右),因为您希望能够处理用户空间应用程序忘记驱动程序的 transient 事件,然后可以稍后处理传入数据。

这就是事情变得不稳定的地方......循环缓冲区是使用 vmalloc32() 分配的,并且来自该分配的页面以与用户空间缓冲区在 AXI-MM 模式下相同的方式映射(即,使用 pci_map_sg() 接口(interface))。结果,因为循环缓冲区在设备和 CPU 之间共享,所以每次 read() 调用都需要我调用 pci_dma_sync_sg_for_cpu()pci_dma_sync_sg_for_device(),这绝对会破坏我的性能(我跟不上设备!),因为它适用于整个缓冲区。有趣的是,Xilinx 从未在他们的代码中包含这些同步调用,所以当我编辑他们的测试脚本以在退出前尝试多次 DMA 传输并且结果数据缓冲区已损坏时,我第一次知道我遇到了问题。

因此,我想知道如何解决这个问题。我考虑过重写代码以构建我自己的使用 pci_alloc_consistent()/dma_alloc_coherent() 分配的缓冲区,但这说起来容易做起来难。也就是说,代码被设计为假设在任何地方都使用分散-聚集列表(在分散-聚集列表和 FPGA 理解的内存描述符之间似乎有一个奇怪的专有映射)。

还有其他任何我应该注意的 API 调用吗?我可以通过某种翻译机制使用“单一”变体(即 pci dma_sync_single_for_cpu())来不同步整个缓冲区吗?或者,是否有一些函数可以使使用 vmalloc() 分配的循环缓冲区保持一致?

最佳答案

好吧,我明白了。

基本上,我对有关同步 API 的内核文档的假设和/或理解是完全错误的。也就是说,我在两个关键假设上错了:

  1. 如果缓冲区从未被 CPU 写入,则您不需要为设备同步。删除此调用使我的 read() 吞吐量翻了一番。
  2. 您不需要同步整个散点列表。相反,现在在我的 read() 调用中,我弄清楚哪些页面将受到 copy_to_user() 调用的影响(即,将要复制的内容循环缓冲区)并且只同步那些我关心的页面。基本上,我可以调用类似 pci_dma_sync_sg_for_cpu(lro->pci_dev, &transfer->sgm->sgl[sgl_index], pages_to_sync, DMA_FROM_DEVICE) 的东西,其中 sgl_index 是我计算复制将开始,pages_to_sync 是数据在页数中的大小。

通过以上两项更改,我的代码现在可以满足我的吞吐量要求。

关于Linux PCIe DMA 驱动程序 (Xilinx XDMA),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48823171/

相关文章:

php - 在 var/www/image 目录中启用写入权限 Ubuntu Server

delphi - 获取特定设备的驱动程序文件

c++ - 如何创建新端口并将其分配给打印机

c++ - Windows 打印处理器可以强制假脱机数据类型吗

linux - 如何在 Arch linux 下使用 Gummiboot 从 Uefi 启动 Xen Hypervisor

linux - 从设备与 sysroot 交叉编译

linux - linux 上 opengl 的 DirectDraw Surface (DDS) 格式的等价物是什么?

c++ - 在 OpenCL 中为嵌入式配置文件创 build 备上下文

audio - 让FPGA使用verilog在 "line out"引脚上输出声音

FPGA 和 PCIe 交换机