You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux PCIe驱动DMA Read正常但DMA Write失败排查求助

PCIe板卡Linux DMA Write流程故障排查

架构

Linux主机 <> PCIe接口 <> 外部PCIe板卡

DMA操作流程

  • 通过IOCTL将用户空间缓冲区传递给驱动(缓冲区包含DMA Write的实际数据和DMA Read的目标位置)
  • 将用户缓冲区转换为SG list
  • 为DMA映射SG list
  • 通过MBOX(寄存器机制)将DMA地址传递给板卡,由板卡侧DMA控制器执行操作

当前实现核心代码

用户空间缓冲区通过copy_from_user()复制到内核空间,核心处理代码:

descriptor = dma_alloc_coherent(&pdev->dev, sizeof(struct dma_descriptor), &dma_handle, GFP_KERNEL);
start = (unsigned long)buffer;
len = do_dma->length;
offset = start & ~PAGE_MASK;
num_pages = (offset + len + PAGE_SIZE - 1) / PAGE_SIZE;
pages = kvmalloc_array(num_pages, sizeof(struct page *), GFP_KERNEL);
pin_user_pages(start, num_pages, FOLL_WRITE | FOLL_LONGTERM | FOLL_FORCE, pages);
sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
sg_alloc_table_from_pages(sgt, pages, num_pages, offset, length, GFP_KERNEL);
dma_map_sgtable(&rtc_dev->pdev->dev, sgt, DMA_BIDIRECTIONAL, 0);

随后将SG list元素复制到struct dma_descriptor中传递给板卡。

故障现象

  • DMA Read流程正常,可接收板卡发送的数据
  • DMA Write流程异常:数据传递给板卡后,板卡DMA控制器持续处于忙碌状态,未触发完成中断;板卡在Windows环境下可正常工作,排除板卡软件问题
  • 怀疑问题出在pin_user_pages()的页面权限上,已尝试FOLL_WRITE | FOLL_FORCE | FOLL_LONGTERM等标志组合,未解决

排查方向建议

1. 页面权限与缓存一致性检查

  • 确认pin_user_pages()的标志匹配DMA方向:DMA Write是主机向板卡传输数据,板卡DMA需要读取用户页面,当前使用的FOLL_WRITE仅允许内核写入页面,需尝试替换为FOLL_READ | FOLL_LONGTERM,确保页面具备被外部设备读取的权限
  • 手动执行缓存同步:在DMA启动前调用dma_sync_sgtable_for_device(&pdev->dev, sgt, DMA_TO_DEVICE),确保用户空间的数据已刷入物理内存,避免板卡DMA读取到缓存中的无效数据

2. SG列表与DMA地址正确性验证

  • 打印SG列表中每个元素的dma_address和长度,对比板卡侧接收的地址是否一致,排查MBOX传递过程中的地址截断、字节序(32位/64位)匹配问题
  • 检查sg_alloc_table_from_pages的length参数:代码中前面定义的变量是len,但调用时用了length,确认是否为笔误,长度计算错误会导致DMA访问超出映射范围,引发控制器挂起

3. DMA映射类型与方向匹配

  • 将dma_map_sgtable的方向参数从DMA_BIDIRECTIONAL改为DMA_TO_DEVICE,明确匹配主机到板卡的传输方向,避免不必要的双向缓存同步操作,修改后代码:
    dma_map_sgtable(&rtc_dev->pdev->dev, sgt, DMA_TO_DEVICE, 0);
    

4. 页面pin的生命周期与释放检查

  • 确认pin_user_pages的返回值是否等于num_pages,排查是否存在部分页面pin失败的情况
  • 确保DMA完成后调用unpin_user_pages释放页面,同时检查FOLL_LONGTERM是否真的禁止了页面swap(可通过/proc/vmstat观察pgout指标确认)

5. 板卡DMA控制器的地址兼容性

  • 确认板卡是否支持IOMMU映射地址:如果系统启用了IOMMU,dma_map_sgtable返回的是IOMMU虚拟地址,若板卡需要直接物理地址,需在驱动中禁用IOMMU,或通过dma_set_mask_and_coherent设置正确的地址掩码

6. 错误处理完善

  • 补充所有API的返回值检查:kvmalloc_array、pin_user_pages、sg_alloc_table_from_pages、dma_map_sgtable的返回值是否正常,避免因资源分配失败导致的隐式错误

内容的提问来源于stack exchange,提问作者Akash Chandra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 23:12:18