6

我正在为 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 边界的地址/长度组合。”

有没有办法获得对齐的地址,或者我只是错过了一些重要的事情?

DMA 的源代码

4

1 回答 1

3

想到的第一种可能性是进入的用户缓冲区不是从页面边界开始的。如果您的起始地址是页面中的 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 事务列表。

于 2012-02-22T09:06:48.537 回答