PXA/MMP - DMA 从控制器¶
约束¶
a) 传输热排队:提交传输并发出传输指令的驱动程序应被保证即使在正在运行的 DMA 通道上也能将传输排队。这意味着排队不会等待上一次传输结束,并且描述符链接不仅仅在传输结束触发的 irq/tasklet 代码中完成。在物理通道上提交并发出的传输不会等待物理通道停止并重新启动,而是在“正在运行的通道”上提交。其他驱动程序,特别是 mmp_pdma,在重新启动新传输之前会等待物理通道停止。
b) 所有请求确认的传输都应发出信号:任何发出 DMA_PREP_INTERRUPT 的传输都应触发回调调用。这意味着,即使 irq/tasklet 是由 tx1 结束触发的,但在 irq/dma 时 tx2 已经完成,也应调用 tx1->complete() 和 tx2->complete()。
c) 通道运行状态:驱动程序应该能够查询通道是否正在运行。对于多媒体情况,例如视频捕获,如果提交传输后检查 DMA 通道报告“停止通道”,则不应发出传输,直到下一个“帧开始中断”,因此需要知道通道处于运行状态还是停止状态。
d) 带宽保证:PXA 架构有 4 个级别的 DMA 优先级:高、正常、低。高优先级获得的带宽是正常的两倍,而正常优先级获得的带宽是低优先级的两倍。驱动程序应该能够请求优先级,特别是像 pxa_camera 这样具有(大)吞吐量的实时驱动程序。
设计¶
a) 虚拟通道:与 sa11x0 驱动程序中的概念相同,即为驱动程序分配一个链接到请求器线路的“虚拟通道”,并且在发出传输时动态分配物理 DMA 通道。
分散-聚集传输的传输结构
+------------+-----+---------------+----------------+-----------------+
| desc-sg[0] | ... | desc-sg[last] | status updater | finisher/linker |
+------------+-----+---------------+----------------+-----------------+
此结构由 dma->sg_cpu 指向。描述符的使用方式如下
desc-sg[i]:第 i 个描述符,将第 i 个 sg 元素传输到视频缓冲区分散聚集
状态更新程序:将单个 u32 传输到众所周知的 DMA 连贯内存,以留下此传输已完成的痕迹。“众所周知”对于每个物理通道都是唯一的,这意味着读取此值将告诉您此时最后一个完成的传输是哪个。
完成器:具有 ddadr=DADDR_STOP,dcmd=ENDIRQEN
链接器:具有下一个传输的 ddadr= desc-sg[0],dcmd=0
c) 传输热链接:假设正在运行的链是
Buffer 1 Buffer 2
+---------+----+---+ +----+----+----+---+
| d0 | .. | dN | l | | d0 | .. | dN | f |
+---------+----+-|-+ ^----+----+----+---+
| |
+----+
在调用 dmaengine_submit(b3) 后,链将如下所示
Buffer 1 Buffer 2 Buffer 3
+---------+----+---+ +----+----+----+---+ +----+----+----+---+
| d0 | .. | dN | l | | d0 | .. | dN | l | | d0 | .. | dN | f |
+---------+----+-|-+ ^----+----+----+-|-+ ^----+----+----+---+
| | | |
+----+ +----+
new_link
如果在创建 new_link 时 DMA 通道停止,则 _不_ 重新启动。热链接不会破坏 dma_async_issue_pending() 用于确保传输实际启动的假设。
此规则的一个例外情况
如果 Buffer1 和 Buffer2 的所有地址都是 8 字节对齐的
并且如果 Buffer3 至少有一个地址不是 4 字节对齐的
则无法进行热链接,因为必须停止通道,必须设置“对齐位”,并且必须重新启动通道。因此,此类传输 tx_submit() 将在已提交队列中排队,并且如果 DMA 已经在对齐模式下运行,则属于此特定情况。
d) 传输完成更新程序:每次通道上的传输完成时,可能会或可能不会根据客户端的请求生成中断。但在每种情况下,传输的最后一个描述符(即“状态更新程序”)会将最新完成的传输写入物理通道的完成标记中。
这将加快残余计算,对于像视频缓冲区这样拥有大约 6k 或更多描述符的大型传输。这也允许在没有任何锁定的情况下找出正在运行的 DMA 链中最新完成的传输是什么。
e) 传输完成、irq 和 tasklet:当标记为“DMA_PREP_INTERRUPT”的传输完成时,会引发 dma irq。在此中断后,会为物理通道调度一个 tasklet。
tasklet 负责
读取物理通道最后一个更新程序的标记
根据该标记和每个传输标志,调用已完成传输的所有传输回调。
如果在此处理完成时传输完成,则将引发 dma irq,并且 tasklet 将再次调度,并具有新的更新程序标记。
f) 残余:残余粒度将基于描述符。将扫描已发出但未完成的传输,以查找其所有描述符与当前正在运行的描述符的对比情况。
g) 驱动程序的 tx 队列最复杂的情况:最棘手的情况是当
没有“已确认”的传输 (tx0)
驱动程序提交了未链接的对齐 tx1
驱动程序提交了对齐的 tx2 => tx2 冷链接到 tx1
驱动程序发出 tx1+tx2 => 通道以对齐模式运行
驱动程序提交了对齐的 tx3 => tx3 热链接
驱动程序提交了未对齐的 tx4 => tx4 被放入已提交队列,未链接
驱动程序发出 tx4 => tx4 被放入已发出队列,未链接
驱动程序提交了对齐的 tx5 => tx5 被放入已提交队列,未链接
驱动程序提交了对齐的 tx6 => tx6 被放入已提交队列,冷链接到 tx5
这转换为(在发出 tx4 后)
已发出队列
+-----+ +-----+ +-----+ +-----+ | tx1 | | tx2 | | tx3 | | tx4 | +---|-+ ^---|-+ ^-----+ +-----+ | | | | +---+ +---+ - submitted queue +-----+ +-----+ | tx5 | | tx6 | +---|-+ ^-----+ | | +---+
已完成队列:空
已分配队列:tx0
应该注意的是,在 tx3 完成后,通道停止,并以“未对齐模式”重新启动以处理 tx4。
作者:Robert Jarzmik <robert.jarzmik@free.fr>