soft raid5阅读笔记之十二--DMA相关

来源:互联网 发布:ecshop大京东3.0源码 编辑:程序博客网 时间:2024/04/28 09:37
1、异步传输描述符(linux/dmaengine.h):
struct dma_async_tx_descriptor {     dma_cookie_t cookie;               /*本次传输的跟踪cookie,如果本次传输位于独立的链表,则设置为-EBUSY*/     enum dma_ctrl_flags flags; /* not a 'long' to pack with cookie */     dma_addr_t phys;                    /*该描述符的物理地址*/     struct dma_chan *chan;          /*本次操作的目标通道*/     dma_cookie_t (*tx_submit)(struct dma_async_tx_descriptor *tx); /*设置准备好的描述符被DMA引擎执行*/     dma_async_tx_callback callback;     /*本次操作完成后的回调函数*/     void *callback_param;                    /*完成回调函数的参数*/     struct dma_async_tx_descriptor *next;     /*完成后递交该描述符*/     struct dma_async_tx_descriptor *parent;     /*升级的下一个描述符*/     spinlock_t lock;};


2、异步传输递交/完成控制器(linux/async_tx.h)
/*** struct async_submit_ctl - async_tx submission/completion modifiers* @flags: submission modifiers* @depend_tx: parent dependency of the current operation being submitted* @cb_fn: callback routine to run at operation completion                       * @cb_param: parameter for the callback routine                                   * @scribble: caller provided space for dma/page address conversions     */struct async_submit_ctl {     enum async_tx_flags flags;                                 /*异步传输标志位*/     struct dma_async_tx_descriptor *depend_tx;     /*相关的DMA异步传输描述符*/     dma_async_tx_callback cb_fn;                          /*操作完成的回调函数*/     void *cb_param;                                              /*完成回调函数的参数*/     void *scribble;                                                  /*调用者提供的dma和页地址转换的空间*/};


3、异步传输标志位
/*** 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),     /*该标志位必须用于目标地址不是源操作数的XOR操作*/     ASYNC_TX_XOR_DROP_DST     = (1 << 1),     /*该标志位必须用于目标地址也是源操作数之一的XOR操作*/     ASYNC_TX_ACK          = (1 << 2),                    /*立即响应该描述符*/     ASYNC_TX_FENCE          = (1 << 3),               /*指定了下一次操作必须使用本次操作的结果作为输入*/};


4、初始化异步操作的控制器:
static inline voidinit_async_submit(struct async_submit_ctl *args, enum async_tx_flags flags,            struct dma_async_tx_descriptor *tx,            dma_async_tx_callback cb_fn, void *cb_param,            addr_conv_t *scribble){     args->flags = flags;     args->depend_tx = tx;     args->cb_fn = cb_fn;     args->cb_param = cb_param;     args->scribble = scribble;}


5、使用DMA引擎异或一系列的块
/*** async_xor - attempt to xor a set of blocks with a dma engine.* @dest: destination page                                        目的页* @src_list: array of source pages                              源页的数组* @offset: common src/dst offset to start transaction  源页/目的页的起始偏移* @src_cnt: number of source pages                            源页的数量* @len: length in bytes                                                  异或的长度* @submit: submission / completion modifiers               提交/完成控制器** honored flags: ASYNC_TX_ACK, ASYNC_TX_XOR_ZERO_DST, ASYNC_TX_XOR_DROP_DST** xor_blocks always uses the dest as a source so the* ASYNC_TX_XOR_ZERO_DST flag must be set to not include dest data in* the calculation.  The assumption with dma eninges is that they only* use the destination buffer as a source when it is explicity specified* in the source list.** src_list note: if the dest is also a source it must be at index zero.* The contents of this array will be overwritten if a scribble region* is not specified.*/struct dma_async_tx_descriptor *async_xor(struct page *dest, struct page **src_list, unsigned int offset,       int src_cnt, size_t len, struct async_submit_ctl *submit){     struct dma_chan *chan = async_tx_find_channel(submit, DMA_XOR,                                    &dest, 1, src_list,                                    src_cnt, len);     dma_addr_t *dma_src = NULL;     BUG_ON(src_cnt <= 1);     if (submit->scribble)          dma_src = submit->scribble;     else if (sizeof(dma_addr_t) <= sizeof(struct page *))          dma_src = (dma_addr_t *) src_list;     if (dma_src && chan && is_dma_xor_aligned(chan->device, offset, 0, len)) {          /* run the xor asynchronously */          pr_debug("%s (async): len: %zu\n", __func__, len);          return do_async_xor(chan, dest, src_list, offset, src_cnt, len,                        dma_src, submit);     } else {          /* run the xor synchronously */          pr_debug("%s (sync): len: %zu\n", __func__, len);          WARN_ONCE(chan, "%s: no space for dma address conversion\n",                 __func__);          /* in the sync case the dest is an implied source          * (assumes the dest is the first source)          */          if (submit->flags & ASYNC_TX_XOR_DROP_DST) {               src_cnt--;               src_list++;          }          /* wait for any prerequisite operations */          async_tx_quiesce(&submit->depend_tx);          do_sync_xor(dest, src_list, offset, src_cnt, len, submit);          return NULL;     }}


6、查找执行该操作的通道或者让该传输同步执行
/*** __async_tx_find_channel - find a channel to carry out the operation or let*     the transaction execute synchronously* @submit: transaction dependency and submission modifiers* @tx_type: transaction type*/struct dma_chan *__async_tx_find_channel(struct async_submit_ctl *submit,               enum dma_transaction_type tx_type){     struct dma_async_tx_descriptor *depend_tx = submit->depend_tx;     /* see if we can keep the chain on one channel */     if (depend_tx &&         dma_has_cap(tx_type, depend_tx->chan->device->cap_mask))          return depend_tx->chan;     return async_dma_find_channel(tx_type);}


0 0
原创粉丝点击