PCIE linux内核驱动程序中的流式DMA

PCIE linux内核驱动程序中的流式DMA,linux,drivers,pci,dma,Linux,Drivers,Pci,Dma,我正在为Linux内核开发FPGA驱动程序。代码在x86上似乎运行良好,但在x86_64上我遇到了一些问题。我实现了流式DMA。事情是这样的 get_user_pages(...); for (...) { sg_set_page(); } pci_map_sg(); 但是pci_map_sg返回的地址如0xbd285800,这些地址不按页面大小对齐,因此我无法发送完整的第一页,因为PCIE规范规定 “请求不得指定导致 跨4-KB边界的内存空间访问。“ 有没有办法让地址保持一致,或者我

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

get_user_pages(...);
for (...) {
    sg_set_page();
}
pci_map_sg();
但是
pci_map_sg
返回的地址如
0xbd285800
,这些地址不按
页面大小对齐,因此我无法发送完整的第一页,因为PCIE规范规定

“请求不得指定导致 跨4-KB边界的内存空间访问。“

有没有办法让地址保持一致,或者我只是错过了一些重要的事情


.

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

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


我处理的许多设备都有DMA引擎,允许我指定数兆字节的逻辑传输长度。通常,PCIe端点中的DMA实现负责在每个4kB边界启动新的PCIe事务,程序员可以忽略该约束。如果FPGA中的资源太有限而无法处理,可以考虑编写驱动程序代码来将Linux内存块列表转换成更长的PCIE事务列表。那里没有足够的东西来发现虫子。是的,当然。附于原始帖子。@soh:有计划向公众发布吗?我四处寻找一个开着的司机,却找不到一个好的。我懒得写自己的代码,我非常乐意为测试做出贡献和帮助。@Vlad Lazarenko:如果您仍然感兴趣,我想在项目结束后我可以分享代码。您好,请尝试一下您的DMA掩码是否为64位DMA_set_maskthank正确设置了很多。用户缓冲区正常,但FPGA PCIE核心不处理长缓冲区。