soh*_*soh 6 linux drivers dma pci
我正在研究用于Linux内核的FPGA驱动程序.代码似乎在x86上工作正常,但在x86_64上我遇到了一些问题.我实现了流式DMA.所以它就像
get_user_pages(...);
for (...) {
sg_set_page();
}
pci_map_sg();
Run Code Online (Sandbox Code Playgroud)
但pci_map_sg返回的地址就像是0xbd285800,它们没有对齐PAGE_SIZE,所以我无法发送完整的第一页,因为PCIE规范说
"请求不得指定地址/长度组合,这会导致内存空间访问跨越4 KB边界."
有没有办法获得对齐的地址,还是我错过了一些重要的东西?
我想到的第一个可能性是传入的用户缓冲区不是从页面边界开始的。如果您的起始地址是一页中的 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 事务列表。
| 归档时间: |
|
| 查看次数: |
3283 次 |
| 最近记录: |