Xilinx的两款FPGA平台xdma和qdma

之前使用过xdma和qdma,但是未对其流程梳理,今天对其DMA操作流程梳理下,以备记录。

首先说一下流式DMA映射和一致性DMA映射:

        流式DMA映射:缓冲区来自叫上层的比如,kmalloc,__get_free_pages 等申请的,一般使用流式DMA映射,流式DMA映射大多进行cache的使无效或清楚操作,以解决cache的一致性问题,

接口较为复杂。

xmda使用流式dma映射:

 dma_map_single(dev, addr, size, direction);
 dma_unmap_single(dev, dma_handle, size, direction);

如果设备要求较大的DMA缓冲区,在支持SG模式时,可申请不连续的DMA缓冲区进行映射。

        一致性DMA映射申请的缓存区能够使用cache,并且保持cache一致性。一致性映射具有很长的生命周期,在这段时间内占用的映射寄存器,即使不使用也不会释放。生命周期为该驱动的生命周期。

        主要用到的函数:

void * dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle,
gfp_t gfp);

上述函数的返回值为申请到的DMA缓冲区的虚拟地址, 此外, 该函数还通过参数handle返回DMA缓
冲区的总线地址。 handle的类型为dma_addr_t, 代表的是总线地址。

void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
dma_addr_t handle);

qdma使用一致性dma映射;

先梳理下qdma:

qdma 顾名思义,即queue dma,在实际使用时,会建立最多2048和字符设备进行数据传输。使用pcie接口,再使用dma传输数据。

pcie驱动的probe过程略去不表,比较通用。

梳理下用户空间的数据是如何通过dma传输搬移的,首先,用户空间传入一个地址指针ptr和长度len,通过系统调用write传到内核空间,ptr是个用户空间的虚拟地址,也不一定是按页对齐的,所以通过 offset_in_page 获取页内的偏移量,再通过  pages_nr = (len + pg_off + PAGE_SIZE - 1) >> PAGE_SHIFT 获取到实际需要的物理页个数。

使用get_user_pages_fast函数 传入用户空间的地址和页个数,锁定用户进程的数据,并将其映射到内核空间的一个地址,及获取物理页。保存好这些数据后,通过 qdma_request 保存这些值,尤其是iocb.sgl,传入到descq_st_c2h_read等函数操作时。

qdma_queue_start -> qdma_descq_alloc_resource -> desc_ring_alloc

调用dma_alloc_coherent

void *dma_alloc_coherent(struct device *dev,size_t size,
dma_addr_t *dma_handle,int flag);函数如下:

返回一个虚拟地址,dma_handle 为总线地址,descq->desc_cmpt 中保存了调用dma_alloc_coherent分配的虚拟地址。

xdma的处理过程:

前一部分处理和qdma大致相同,传入用户空间的地址buf和长度len。

unsigned int pages_nr = (((unsigned long)buf + len + PAGE_SIZE - 1) -

                 ((unsigned long)buf & PAGE_MASK))

                >> PAGE_SHIFT; 获取实际所需的页帧个数。

sg_alloc_table

sg的详细内容可参考http://www.wowotech.net/memory_management/scatterlist.html

再调用get_user_pages_fast

offset_in_page 获取页内偏移

flush_dcache_page

如果高速缓存包含几个虚拟地址不同项指向内存中的同一页,可能会发生所谓的alias问题,flush_dcache_page有助于防止该问题

sg_set_page

还有最后一点,使用spin_lock  和spin_lock_irqsave的区别:

在任何情况下使用spin_lock_irq都是安全的。因为它既禁止本地中断,又禁止内核抢占。

spin_lock比spin_lock_irq速度快,但是它并不是任何情况下都是安全的。在同一个CPU上的中断可能会导致死锁。

  • 8
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知秋贺

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值