在PCIE linux内核驱动程序中流式传输DMA

前端之家收集整理的这篇文章主要介绍了在PCIE linux内核驱动程序中流式传输DMA前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

我正在研究用于Linux内核的FPGA驱动程序.代码似乎在x86上工作正常,但在x86_64上我遇到了一些问题.我实现了流式DMA.所以它就像

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

但pci_map_sg返回的地址如0xbd285800,没有通过PAGE_SIZE对齐,所以我无法发送完整的第一页,因为PCIE规范说

“Requests must not specify an Address/Length combination which causes
a Memory Space access to cross a 4-KB boundary.”

有没有办法获得对齐的地址,还是我错过了一些重要的东西?

Source code of DMA.

最佳答案
想到的第一种可能性是进入的用户缓冲区不会在页面边界上开始.如果您的起始地址是一个页面的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事务列表.

猜你在找的Linux相关文章