linux - PCIE linux 内核驱动程序中的流式 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 的地址,这些地址没有按 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 - PCIE linux 内核驱动程序中的流式 DMA,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9381571/

相关文章:

linux - 使用 awk 查找可变长度的正则表达式并根据找到的长度编辑以下行

linux - 如何练习编写真正的 Linux 设备驱动程序?

linux - Unix 中的键盘设备

linux - PCI 枚举 hack 以数据中止异常结束

自定义 PCI 驱动程序无法探测设备

c - 注册为线程局部变量

linux - 你能帮我使用 smbclient 从 Ubuntu 访问 Mac SMB 共享吗? (NT_STATUS_ACCESS_DENIED 错误)

linux - 停止脚本 |龙头 |重新连接到分离的 screen

windows - 关于NTFS过滤驱动的问题

pci - 总线上的PCI设备能否监听其他设备数据?