全部博文(127)
分类:
2012-12-14 13:54:41
原文地址:linux 2.6.32 Async_tx代码分析 二 作者:libing881
继续分析Async_tx的头文件,
/* on architectures without dma-mapping capabilities we need to ensure * that the asynchronous path compiles away */ #ifdef CONFIG_HAS_DMA #define __async_inline #else #define __async_inline __always_inline #endif
在没有DMA映射的架构下,使用宏值来保证编译成inline???
/** * dma_chan_ref - object used to manage dma channels received from the * dmaengine core. * @chan - the channel being tracked * @node - node for the channel to be placed on async_tx_master_list * @rcu - for list_del_rcu * @count - number of times this channel is listed in the pool * (for channels with multiple capabiities) */ struct dma_chan_ref { struct dma_chan *chan; struct list_head node; struct rcu_head rcu; atomic_t count; };
这里面有2个概念,一个是dma channels,一个是dmaengine。dma通道可以认为是逻辑上的,也可以认为就是对应了CPU上的一个物理的DMA通道。通常CPU和DMA芯片之间有多个通道连接,每一个通道都有硬件厂商定义的DMA能力。比如可以有0、1、2、3,共4个通道,CPU厂商定义4个通道都可以进行DMA内存搬运操作,并且0、1通道有DMA raid能力,这里主要指得是raid5、raid6的异或和PQ计算能力。
Async_tx起的是一个隔离底层硬件差异的中间层,不管底层的CPU是Intel的,还是AMD,还是MIPS的,只要底层驱动提供了通道抽象的实现,上层应用,这里主要是指的raid5、6就不需要修改代码,直接使用Async_tx的API就可以完成raid栈的功能。这里还要提醒,就算底层没有DMA能力,Async_tx也可以自动识别,自动使用CPU来直接memcpy或进行xor计算。
另外Async_tx还提供了通道切换的服务,含义是一些特定的操作,比如raid5的memcpy-->xor-->memcpy操作,这个是必须是连续执行的,后面的操作依赖前一步的结果,这个时候,上层不必关心底层的细节,Async_tx可以将这些操作串成一个chain,一次发送到同一个通道上执行。而由于通道需要重新配置才能提供不同的能力,这个通道切换就由底层提供回调接口,在Async_tx框架内自动执行。
/** * async_tx_flags - modifiers for the async_* calls * @ASYNC_TX_XOR_ZERO_DST: this flag must be used for xor operations where the * the destination address is not a source. The asynchronous case handles this * implicitly, the synchronous case needs to zero the destination block. * @ASYNC_TX_XOR_DROP_DST: this flag must be used if the destination address is * also one of the source addresses. In the synchronous case the destination * address is an implied source, whereas the asynchronous case it must be listed * as a source. The destination address must be the first address in the source * array. * @ASYNC_TX_ACK: immediately ack the descriptor, precludes setting up a * dependency chain * @ASYNC_TX_FENCE: specify that the next operation in the dependency * chain uses this operation's result as an input */ enum async_tx_flags { ASYNC_TX_XOR_ZERO_DST = (1 << 0), ASYNC_TX_XOR_DROP_DST = (1 << 1), ASYNC_TX_ACK = (1 << 2), ASYNC_TX_FENCE = (1 << 3), };
4个枚举变量,作为异步调用的必填的flag,每个都必须在合适的情况下调用,
* @ASYNC_TX_XOR_ZERO_DST: 该标记必须在xor操作下使用,当目的地址不是源地址的时候。在异步情况下,清0是隐含的,而同步模式下需要清0目的块。这也很显然,先把目的地址清个0,然后将计算出来的xor值拷到目的地址中去,避免一些可能错误。
* @ASYNC_TX_XOR_DROP_DST: 该标记必须在当目的地址也是源地址的情况下使用。在同步执行模式下,这个是隐含操作。但是在异步执行模式下,必须将目的地址放到为源地址列表。而且目的地址必须是源地址列表中的第一个。
* @ASYNC_TX_ACK: 立即应答描述符,组织设置关联chain。也就是最常用的,如果没有什么关联关系的操作,一般就设置为这个flag
* @ASYNC_TX_FENCE: 制定下一个依赖操作使用本次操作的结果作为输入