【问题标题】:Streaming DMA in PCIE linux kernel driverPCIE linux内核驱动程序中的流式DMA
【发布时间】:2012-03-12 00:00:20
【问题描述】:

我正在为 Linux 内核开发 FPGA 驱动程序。代码似乎在 x86 上运行良好,但在 x86_64 上我遇到了一些问题。我实现了流式 DMA。就这样

get_user_pages(...);
for (...) {
    sg_set_page();
}
pci_map_sg();

但是pci_map_sg返回的地址如0xbd285800,与PAGE_SIZE不对齐,所以我不能发送完整的第一页,因为PCIE规范说

"请求不能指定地址/长度组合,这会导致 跨越 4 KB 边界的内存空间访问。”

有什么方法可以得到对齐的地址,还是我错过了一些重要的事情?

Source code of DMA.

【问题讨论】:

  • 你能包含你真实来源的代码吗?那里不足以发现错误。
  • 是的,当然。附于原帖。
  • @soh:有计划向公众发布它吗?我正在四处寻找一个开放的驱动程序,但找不到一个好的驱动程序。懒得自己写,我很乐意为测试做出贡献和帮助。
  • @Vlad Lazarenko:如果你还有兴趣,我想在项目结束后我可以分享代码。
  • 您好,请尝试为 64 位 dma_set_mask 正确设置您的 DMA 掩码

标签: linux drivers pci dma


【解决方案1】:

首先想到的可能是进入的用户缓冲区不是从页面边界开始的。如果您的起始地址是页面中的 0x800 字节,那么您的第一个 sg_set_page 调用的偏移量将为 0x800。这将产生一个以 0x800 结尾的 DMA 地址。这是正常的事情,而不是错误。

pci_map_sg 合并页面时,这第一段可能大于一页。重要的是pci_map_sg 生成连续的 DMA 可寻址内存块,但它不生成低级 PCIe 事务列表。在 x64 上,您更有可能获得较大的区域,因为大多数 x64 平台都有 IOMMU。

我处理的许多设备都有 DMA 引擎,允许我指定几兆字节的逻辑传输长度。通常,PCIe 端点中的 DMA 实现负责在每个 4kB 边界处启动新的 PCIe 事务,程序员可以忽略该约束。如果 FPGA 中的资源太有限而无法处理,您可以考虑编写驱动程序代码,将 Linux 内存块列表转换为(更长的)PCIe 事务列表。

【讨论】:

  • 非常感谢。用户缓冲区没问题,但 FPGA PCIE 内核不处理长缓冲区。
猜你喜欢
  • 2019-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-05
  • 2015-12-31
  • 1970-01-01
相关资源
最近更新 更多