towards an async_tx update for 2.6.25
Subsystems (4)
cover towards an async_tx update for 2.6.25
Prompted by Yuri's RAID6 acceleration implementation [1], and Haavard's DMA-slave interface [2], this series cleans up the async_tx api and prepares it for these new features. The most invasive change is the removal of the tx_set_src and tx_set_dest methods in patch 2/4, drivers now receive all necessary operation information at 'prep' time.
Still on the to do list:
* Pull the mpc85xx driver from -mm and integrate these api changes
* Apply Haavard's dma-test-client [3]. Look into extending it for other operations and async_tx channel switching testing
* Teach async_tx about drivers that do not support channel switching
This series is based on 2.6.24-rc6.
Dan Williams (4):
async_tx: kill ASYNC_TX_ASSUME_COHERENT
async_tx: kill tx_set_src and tx_set_dest methods
async_tx: replace 'int_en' with operation preparation flags
async_tx: allow architecture specific async_tx_find_channel implementations
crypto/async_tx/async_memcpy.c | 38 ++++----- crypto/async_tx/async_memset.c | 28 +++--- crypto/async_tx/async_tx.c | 6 +- crypto/async_tx/async_xor.c | 120 +++++++++++++++++------------ drivers/dma/Kconfig | 1 + drivers/dma/dmaengine.c | 49 +++++++----- drivers/dma/ioat_dma.c | 43 ++++------ drivers/dma/iop-adma.c | 136 ++++++++++++-------------------- include/asm-arm/arch-iop13xx/adma.h | 18 +++-- include/asm-arm/hardware/iop3xx-adma.h | 30 ++++--- include/linux/async_tx.h | 13 ++- include/linux/dmaengine.h | 29 ++++--- 12 files changed, 253 insertions(+), 258 deletions(-)
--
Dan
[1] http://marc.info/?l=linux-raid&m=119676789912370&w=2
[2] http://marc.info/?l=linux-kernel&m=119582072930013&w=2
[3] http://marc.info/?l=linux-kernel&m=119583211214496&w=2
PATCH 1/4 async_tx: kill ASYNC_TX_ASSUME_COHERENT
Remove the unused ASYNC_TX_ASSUME_COHERENT flag. Async_tx is meant to hide the difference between asynchronous hardware and synchronous software operations, this flag requires clients to understand cache coherency consequences of the async path.
---
crypto/async_tx/async_memcpy.c | 15 +++++---------- crypto/async_tx/async_memset.c | 8 +++----- crypto/async_tx/async_xor.c | 22 ++++++---------------- include/linux/async_tx.h | 2 -- 4 files changed, 14 insertions(+), 33 deletions(-)
crypto/async_tx/async_memcpy.c +5 -10
@@ -35,7 +35,7 @@* @src: src page * @offset: offset in pages to start transaction * @len: length in bytes -* @flags: ASYNC_TX_ASSUME_COHERENT, ASYNC_TX_ACK, ASYNC_TX_DEP_ACK, +* @flags: ASYNC_TX_ACK, ASYNC_TX_DEP_ACK, * @depend_tx: memcpy depends on the result of this transaction * @cb_fn: function to call when the memcpy completes * @cb_param: parameter to pass to the callback routine
@@ -55,20 +55,15 @@ async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,if (tx) {/* run the memcpy asynchronously */ dma_addr_t addr; -enum dma_data_direction dir;pr_debug ("%s: (async) len: %zu\n" , __FUNCTION__, len); - dir = (flags &ASYNC_TX_ASSUME_COHERENT ) ? -DMA_NONE :DMA_FROM_DEVICE ; - - addr =dma_map_page (device->dev, dest, dest_offset, len, dir); + addr =dma_map_page (device->dev, dest, dest_offset, len, +DMA_FROM_DEVICE ); tx->tx_set_dest (addr, tx,0 ); - dir = (flags &ASYNC_TX_ASSUME_COHERENT ) ? -DMA_NONE :DMA_TO_DEVICE ; - - addr =dma_map_page (device->dev, src, src_offset, len, dir); + addr =dma_map_page (device->dev, src, src_offset, len, +DMA_TO_DEVICE ); tx->tx_set_src (addr, tx,0 );async_tx_submit (chan, tx, flags, depend_tx, cb_fn, cb_param);
crypto/async_tx/async_memset.c +3 -5
@@ -35,7 +35,7 @@* @val: fill value * @offset: offset in pages to start transaction * @len: length in bytes -* @flags: ASYNC_TX_ASSUME_COHERENT, ASYNC_TX_ACK, ASYNC_TX_DEP_ACK +* @flags: ASYNC_TX_ACK, ASYNC_TX_DEP_ACK * @depend_tx: memset depends on the result of this transaction * @cb_fn: function to call when the memcpy completes * @cb_param: parameter to pass to the callback routine
@@ -55,13 +55,11 @@ async_memset(struct page *dest, int val, unsigned int offset,if (tx) {/* run the memset asynchronously */ dma_addr_t dma_addr; -enum dma_data_direction dir;pr_debug ("%s: (async) len: %zu\n" , __FUNCTION__, len); - dir = (flags &ASYNC_TX_ASSUME_COHERENT ) ? -DMA_NONE :DMA_FROM_DEVICE ; - dma_addr =dma_map_page (device->dev, dest, offset, len, dir); + dma_addr =dma_map_page (device->dev, dest, offset, len, +DMA_FROM_DEVICE ); tx->tx_set_dest (dma_addr, tx,0 );async_tx_submit (chan, tx, flags, depend_tx, cb_fn, cb_param);
crypto/async_tx/async_xor.c +6 -16
@@ -38,23 +38,17 @@ do_async_xor(struct dma_async_tx_descriptor *tx, struct dma_device *device, dma_async_tx_callback cb_fn, void *cb_param) { dma_addr_t dma_addr; -enum dma_data_direction dir;int i;pr_debug ("%s: len: %zu\n" , __FUNCTION__, len); - dir = (flags &ASYNC_TX_ASSUME_COHERENT ) ? -DMA_NONE :DMA_FROM_DEVICE ; - - dma_addr =dma_map_page (device->dev, dest, offset, len, dir); + dma_addr =dma_map_page (device->dev, dest, offset, len, +DMA_FROM_DEVICE ); tx->tx_set_dest (dma_addr, tx,0 ); - dir = (flags &ASYNC_TX_ASSUME_COHERENT ) ? -DMA_NONE :DMA_TO_DEVICE ; -for (i =0 ; i < src_cnt; i++) { dma_addr =dma_map_page (device->dev, src_list[i], - offset, len, dir); + offset, len,DMA_TO_DEVICE ); tx->tx_set_src (dma_addr, tx, i); }
@@ -102,7 +96,7 @@ do_sync_xor(struct page *dest, struct page **src_list, unsigned int offset,* @src_cnt: number of source pages * @len: length in bytes * @flags: ASYNC_TX_XOR_ZERO_DST, ASYNC_TX_XOR_DROP_DEST, -* ASYNC_TX_ASSUME_COHERENT, ASYNC_TX_ACK, ASYNC_TX_DEP_ACK +* ASYNC_TX_ACK, ASYNC_TX_DEP_ACK * @depend_tx: xor depends on the result of this transaction. * @cb_fn: function to call when the xor completes * @cb_param: parameter to pass to the callback routine
@@ -242,7 +236,7 @@ static int page_is_zero(struct page *p, unsigned int offset, size_t len)* @src_cnt: number of source pages * @len: length in bytes * @result: 0 if sum == 0 else non-zero -* @flags: ASYNC_TX_ASSUME_COHERENT, ASYNC_TX_ACK, ASYNC_TX_DEP_ACK +* @flags: ASYNC_TX_ACK, ASYNC_TX_DEP_ACK * @depend_tx: xor depends on the result of this transaction. * @cb_fn: function to call when the xor completes * @cb_param: parameter to pass to the callback routine
@@ -266,16 +260,12 @@ async_xor_zero_sum(struct page *dest, struct page **src_list,if (tx) {dma_addr_t dma_addr; -enum dma_data_direction dir;pr_debug ("%s: (async) len: %zu\n" , __FUNCTION__, len); - dir = (flags &ASYNC_TX_ASSUME_COHERENT ) ? -DMA_NONE :DMA_TO_DEVICE ; -for (i =0 ; i < src_cnt; i++) { dma_addr =dma_map_page (device->dev, src_list[i], - offset, len, dir); + offset, len,DMA_TO_DEVICE ); tx->tx_set_src (dma_addr, tx, i); }
include/linux/async_tx.h +0 -2
@@ -47,7 +47,6 @@ struct dma_chan_ref {* 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_ASSUME_COHERENT: skip cache maintenance operations * @ASYNC_TX_ACK: immediately ack the descriptor, precludes setting up a * dependency chain * @ASYNC_TX_DEP_ACK: ack the dependency descriptor. Useful for chaining.
@@ -55,7 +54,6 @@ struct dma_chan_ref {enum async_tx_flags {ASYNC_TX_XOR_ZERO_DST = (1 <<0 ),ASYNC_TX_XOR_DROP_DST = (1 <<1 ), -ASYNC_TX_ASSUME_COHERENT = (1 <<2 ),ASYNC_TX_ACK = (1 <<3 ),ASYNC_TX_DEP_ACK = (1 <<4 ), };
PATCH 2/4 async_tx: kill tx_set_src and tx_set_dest methods
In reply to Dan WilliamsThe tx_set_src and tx_set_dest methods were originally implemented to allow an array of addresses to be passed down from async_xor to the dmaengine driver while minimizing stack overhead. Removing these methods allows drivers to have all transaction parameters available at 'prep' time, saves two function pointers in struct dma_async_tx_descriptor, and reduces the number of indirect branches..
A consequence of moving this data to the 'prep' routine is that multi-source routines like async_xor need temporary storage to convert an array of linear addresses into an array of dma addresses. In order to keep the same stack footprint of the previous implementation the input array is reused as storage for the dma addresses. This requires that sizeof(dma_addr_t) be less than or equal to sizeof(void *). As a consequence CONFIG_DMADEVICES now depends on !CONFIG_HIGHMEM64G. It also requires that drivers be able to make descriptor resources available when the 'prep' routine is polled.
---
crypto/async_tx/async_memcpy.c | 27 ++++----- crypto/async_tx/async_memset.c | 20 +++--- crypto/async_tx/async_xor.c | 94 +++++++++++++++++++----------- drivers/dma/Kconfig | 1 drivers/dma/dmaengine.c | 49 +++++++++------- drivers/dma/ioat_dma.c | 39 +++++-------- drivers/dma/iop-adma.c | 124 ++++++++++++++-------------------------- include/linux/dmaengine.h | 20 +++--- 8 files changed, 178 insertions(+), 196 deletions(-)
crypto/async_tx/async_memcpy.c +13 -14
@@ -48,26 +48,25 @@ async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset, {struct dma_chan *chan =async_tx_find_channel (depend_tx,DMA_MEMCPY );struct dma_device *device = chan ? chan->device :NULL ; -int int_en = cb_fn ?1 :0 ; -struct dma_async_tx_descriptor *tx = device ? - device->device_prep_dma_memcpy (chan, len, - int_en) :NULL ; +struct dma_async_tx_descriptor *tx =NULL ; -if (tx) {/* run the memcpy asynchronously */ -dma_addr_t addr; +if (device) { +dma_addr_t dma_dest, dma_src; -pr_debug ("%s: (async) len: %zu\n" , __FUNCTION__, len); + dma_dest =dma_map_page (device->dev, dest, dest_offset, len, +DMA_FROM_DEVICE ); - addr =dma_map_page (device->dev, dest, dest_offset, len, -DMA_FROM_DEVICE ); - tx->tx_set_dest (addr, tx,0 ); + dma_src =dma_map_page (device->dev, src, src_offset, len, +DMA_TO_DEVICE ); - addr =dma_map_page (device->dev, src, src_offset, len, -DMA_TO_DEVICE ); - tx->tx_set_src (addr, tx,0 ); + tx = device->device_prep_dma_memcpy (chan, dma_dest, dma_src, + len, cb_fn !=NULL ); + } +if (tx) { +pr_debug ("%s: (async) len: %zu\n" , __FUNCTION__, len);async_tx_submit (chan, tx, flags, depend_tx, cb_fn, cb_param); - }else {/* run the memcpy synchronously */ + }else {void *dest_buf, *src_buf;pr_debug ("%s: (sync) len: %zu\n" , __FUNCTION__, len);
crypto/async_tx/async_memset.c +10 -10
@@ -48,20 +48,20 @@ async_memset(struct page *dest, int val, unsigned int offset, {struct dma_chan *chan =async_tx_find_channel (depend_tx,DMA_MEMSET );struct dma_device *device = chan ? chan->device :NULL ; -int int_en = cb_fn ?1 :0 ; -struct dma_async_tx_descriptor *tx = device ? - device->device_prep_dma_memset (chan, val, len, - int_en) :NULL ; +struct dma_async_tx_descriptor *tx =NULL ; -if (tx) {/* run the memset asynchronously */ -dma_addr_t dma_addr; +if (device) { +dma_addr_t dma_dest; -pr_debug ("%s: (async) len: %zu\n" , __FUNCTION__, len); - - dma_addr =dma_map_page (device->dev, dest, offset, len, + dma_dest =dma_map_page (device->dev, dest, offset, len,DMA_FROM_DEVICE ); - tx->tx_set_dest (dma_addr, tx,0 ); + tx = device->device_prep_dma_memset (chan, dma_dest, val, len, + cb_fn !=NULL ); + } + +if (tx) { +pr_debug ("%s: (async) len: %zu\n" , __FUNCTION__, len);async_tx_submit (chan, tx, flags, depend_tx, cb_fn, cb_param); }else {/* run the memset synchronously */ void *dest_buf;
crypto/async_tx/async_xor.c +60 -34
145 lines not on this page · raw message
drivers/dma/Kconfig +1 -0
@@ -5,6 +5,7 @@ menuconfig DMADEVICES bool "DMA Engine support" depends on (PCI && X86) || ARCH_IOP32X || ARCH_IOP33X || ARCH_IOP13XX + depends on !HIGHMEM64G help DMA engines can do asynchronous data transfers without involving the host CPU. Currently, this framework can be
drivers/dma/dmaengine.c +28 -21
88 lines not on this page · raw message
drivers/dma/ioat_dma.c +15 -24
@@ -159,20 +159,6 @@ static int ioat_dma_enumerate_channels(struct ioatdma_device *device)return device->common.chancnt; } -static void ioat_set_src (dma_addr_t addr, -struct dma_async_tx_descriptor *tx, -int index) -{ -tx_to_ioat_desc (tx)->src = addr; -} - -static void ioat_set_dest (dma_addr_t addr, -struct dma_async_tx_descriptor *tx, -int index) -{ -tx_to_ioat_desc (tx)->dst = addr; -} -/** * ioat_dma_memcpy_issue_pending - push potentially unrecognized appended * descriptors to hw
@@ -415,8 +401,6 @@ static struct ioat_desc_sw *ioat_dma_alloc_descriptor(memset (desc,0 ,sizeof (*desc));dma_async_tx_descriptor_init (&desc_sw->async_tx, &ioat_chan->common); - desc_sw->async_tx.tx_set_src = ioat_set_src; - desc_sw->async_tx.tx_set_dest = ioat_set_dest;switch (ioat_chan->device->version) {case IOAT_VER_1_2 : desc_sw->async_tx.tx_submit = ioat1_tx_submit;
@@ -714,6 +698,8 @@ static struct ioat_desc_sw *ioat_dma_get_next_descriptor(static struct dma_async_tx_descriptor *ioat1_dma_prep_memcpy (struct dma_chan *chan, +dma_addr_t dma_dest, +dma_addr_t dma_src,size_t len,int int_en) {
@@ -726,6 +712,8 @@ static struct dma_async_tx_descriptor *ioat1_dma_prep_memcpy(if (new) { new->len = len; + new->dst = dma_dest; + new->src = dma_src;return &new->async_tx; }else return NULL ;
@@ -733,6 +721,8 @@ static struct dma_async_tx_descriptor *ioat1_dma_prep_memcpy(static struct dma_async_tx_descriptor *ioat2_dma_prep_memcpy (struct dma_chan *chan, +dma_addr_t dma_dest, +dma_addr_t dma_src,size_t len,int int_en) {
@@ -749,6 +739,8 @@ static struct dma_async_tx_descriptor *ioat2_dma_prep_memcpy(if (new) { new->len = len; + new->dst = dma_dest; + new->src = dma_src;return &new->async_tx; }else return NULL ;
@@ -1045,7 +1037,7 @@ static int ioat_dma_self_test(struct ioatdma_device *device)u8 *dest;struct dma_chan *dma_chan;struct dma_async_tx_descriptor *tx; -dma_addr_t addr; +dma_addr_t dma_dest, dma_src;dma_cookie_t cookie;int err =0 ;
@@ -1073,7 +1065,12 @@ static int ioat_dma_self_test(struct ioatdma_device *device) goto out; } - tx = device->common.device_prep_dma_memcpy (dma_chan,IOAT_TEST_SIZE ,0 ); + dma_src =dma_map_single (dma_chan->device->dev, src,IOAT_TEST_SIZE , +DMA_TO_DEVICE ); + dma_dest =dma_map_single (dma_chan->device->dev, dest,IOAT_TEST_SIZE , +DMA_FROM_DEVICE ); + tx = device->common.device_prep_dma_memcpy (dma_chan, dma_dest, dma_src, +IOAT_TEST_SIZE ,0 );if (!tx) {dev_err (&device->pdev->dev,"Self-test prep failed, disabling\n" );
@@ -1082,12 +1079,6 @@ static int ioat_dma_self_test(struct ioatdma_device *device) }async_tx_ack (tx); - addr =dma_map_single (dma_chan->device->dev, src,IOAT_TEST_SIZE , -DMA_TO_DEVICE ); - tx->tx_set_src (addr, tx,0 ); - addr =dma_map_single (dma_chan->device->dev, dest,IOAT_TEST_SIZE , -DMA_FROM_DEVICE ); - tx->tx_set_dest (addr, tx,0 ); tx->callback = ioat_dma_test_callback; tx->callback_param = (void *)0x8086 ; cookie = tx->tx_submit (tx);
drivers/dma/iop-adma.c +43 -81
235 lines not on this page · raw message
include/linux/dmaengine.h +8 -12
@@ -209,8 +209,6 @@ typedef void (*dma_async_tx_callback)(void *dma_async_param);* descriptors * @chan: target channel for this operation * @tx_submit: set the prepared descriptor(s) to be executed by the engine -* @tx_set_dest: set a destination address in a hardware descriptor -* @tx_set_src: set a source address in a hardware descriptor * @callback: routine to call after this operation is complete * @callback_param: general parameter to pass to the callback routine * ---async_tx api specific fields---
@@ -227,10 +225,6 @@ struct dma_async_tx_descriptor {struct list_head tx_list;struct dma_chan *chan;dma_cookie_t (*tx_submit)(struct dma_async_tx_descriptor *tx); -void (*tx_set_dest)(dma_addr_t addr, -struct dma_async_tx_descriptor *tx,int index); -void (*tx_set_src)(dma_addr_t addr, -struct dma_async_tx_descriptor *tx,int index);dma_async_tx_callback callback;void *callback_param;struct list_head depend_list;
@@ -279,15 +273,17 @@ struct dma_device {void (*device_free_chan_resources)(struct dma_chan *chan);struct dma_async_tx_descriptor *(*device_prep_dma_memcpy)( -struct dma_chan *chan,size_t len,int int_en); +struct dma_chan *chan,dma_addr_t dest,dma_addr_t src, +size_t len,int int_en);struct dma_async_tx_descriptor *(*device_prep_dma_xor)( -struct dma_chan *chan,unsigned int src_cnt,size_t len, -int int_en); +struct dma_chan *chan,dma_addr_t dest,dma_addr_t *src, +unsigned int src_cnt,size_t len,int int_en);struct dma_async_tx_descriptor *(*device_prep_dma_zero_sum)( -struct dma_chan *chan,unsigned int src_cnt,size_t len, -u32 *result,int int_en); +struct dma_chan *chan,dma_addr_t *src,unsigned int src_cnt, +size_t len,u32 *result,int int_en);struct dma_async_tx_descriptor *(*device_prep_dma_memset)( -struct dma_chan *chan,int value,size_t len,int int_en); +struct dma_chan *chan,dma_addr_t dest,int value,size_t len, +int int_en);struct dma_async_tx_descriptor *(*device_prep_dma_interrupt)(struct dma_chan *chan);
RE: [PATCH 2/4] async_tx: kill tx_set_src and tx_set_dest methods
Quoted 27 lines
From: Williams, Dan J
The
tx_set_srcandtx_set_destmethods were originally implemented to allow
an array of addresses to be passed down fromasync_xorto the dmaengine driver while minimizing stack overhead. Removing these methods allows drivers to have all transaction parameters available at 'prep' time, saves
two function pointers in structdma_async_tx_descriptor, and reduces the
number of indirect branches..A consequence of moving this data to the 'prep' routine is that multi-source routines like
async_xorneed temporary storage to convert an
array of linear addresses into an array of dma addresses. In order to keep
the same stack footprint of the previous implementation the input array is
reused as storage for the dma addresses. This requires thatsizeof(dma_addr_t)be less than or equal tosizeof(void *). As a consequenceCONFIG_DMADEVICESnow depends on !CONFIG_HIGHMEM64G. It also
requires that drivers be able to make descriptor resources available when
the 'prep' routine is polled.
Quoted 2 lines
Signed-off-by Dan Williams <[email protected]>---
[... Snip ...]
Sorry I took so long to get back to this. The ioatdma related changes look fine - I like this approach much better.
Acked by: Shannon Nelson <[email protected]>
PATCH 3/4 async_tx: replace 'int_en' with operation preparation flags
In reply to Dan WilliamsPass a full set of flags to drivers' per-operation 'prep' routines. Currently the only flag passed is DMA_PREP_INTERRUPT. The expectation is that arch-specific async_tx_find_channel() implementations can exploit this capability to find the best channel for an operation.
---
crypto/async_tx/async_memcpy.c | 3 ++- crypto/async_tx/async_memset.c | 3 ++- crypto/async_tx/async_xor.c | 10 ++++++---- drivers/dma/ioat_dma.c | 4 ++-- drivers/dma/iop-adma.c | 20 ++++++++++---------- include/asm-arm/arch-iop13xx/adma.h | 18 ++++++++++-------- include/asm-arm/hardware/iop3xx-adma.h | 30 +++++++++++++++++------------- include/linux/dmaengine.h | 17 +++++++++++++---- 8 files changed, 62 insertions(+), 43 deletions(-)
crypto/async_tx/async_memcpy.c +2 -1
@@ -52,6 +52,7 @@ async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,if (device) {dma_addr_t dma_dest, dma_src; +unsigned long dma_prep_flags = cb_fn ?DMA_PREP_INTERRUPT :0 ; dma_dest =dma_map_page (device->dev, dest, dest_offset, len,DMA_FROM_DEVICE );
@@ -60,7 +61,7 @@ async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset, DMA_TO_DEVICE); tx = device->device_prep_dma_memcpy (chan, dma_dest, dma_src, - len, cb_fn !=NULL ); + len, dma_prep_flags); }if (tx) {
crypto/async_tx/async_memset.c +2 -1
@@ -52,12 +52,13 @@ async_memset(struct page *dest, int val, unsigned int offset,if (device) {dma_addr_t dma_dest; +unsigned long dma_prep_flags = cb_fn ?DMA_PREP_INTERRUPT :0 ; dma_dest =dma_map_page (device->dev, dest, offset, len,DMA_FROM_DEVICE ); tx = device->device_prep_dma_memset (chan, dma_dest, val, len, - cb_fn !=NULL ); + dma_prep_flags); }if (tx) {
crypto/async_tx/async_xor.c +6 -4
@@ -41,6 +41,7 @@ do_async_xor(struct dma_device *device,dma_addr_t *dma_src = (dma_addr_t *) src_list;struct dma_async_tx_descriptor *tx;int i; +unsigned long dma_prep_flags = cb_fn ?DMA_PREP_INTERRUPT :0 ;pr_debug ("%s: len: %zu\n" , __FUNCTION__, len);
@@ -56,7 +57,7 @@ do_async_xor(struct dma_device *device,* in case they can not provide a descriptor */ tx = device->device_prep_dma_xor (chan, dma_dest, dma_src, src_cnt, len, - cb_fn !=NULL ); + dma_prep_flags);if (!tx) {if (depend_tx)dma_wait_for_async_tx (depend_tx);
@@ -64,7 +65,7 @@ do_async_xor(struct dma_device *device,while (!tx) tx = device->device_prep_dma_xor (chan, dma_dest, dma_src, src_cnt, len, - cb_fn !=NULL ); + dma_prep_flags); }async_tx_submit (chan, tx, flags, depend_tx, cb_fn, cb_param);
@@ -264,6 +265,7 @@ async_xor_zero_sum(struct page *dest, struct page **src_list,if (device) {dma_addr_t *dma_src = (dma_addr_t *) src_list; +unsigned long dma_prep_flags = cb_fn ?DMA_PREP_INTERRUPT :0 ;int i;pr_debug ("%s: (async) len: %zu\n" , __FUNCTION__, len);
@@ -274,7 +276,7 @@ async_xor_zero_sum(struct page *dest, struct page **src_list, tx = device->device_prep_dma_zero_sum (chan, dma_src, src_cnt, len, result, - cb_fn !=NULL ); + dma_prep_flags);if (!tx) {if (depend_tx)dma_wait_for_async_tx (depend_tx);
@@ -282,7 +284,7 @@ async_xor_zero_sum(struct page *dest, struct page **src_list,while (!tx) tx = device->device_prep_dma_zero_sum (chan, dma_src, src_cnt, len, result, - cb_fn !=NULL ); + dma_prep_flags); }async_tx_submit (chan, tx, flags, depend_tx, cb_fn, cb_param);
drivers/dma/ioat_dma.c +2 -2
@@ -701,7 +701,7 @@ static struct dma_async_tx_descriptor *ioat1_dma_prep_memcpy(dma_addr_t dma_dest, dma_addr_t dma_src, size_t len, - int int_en) + unsigned long flags) { struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);struct ioat_desc_sw *new;
@@ -724,7 +724,7 @@ static struct dma_async_tx_descriptor *ioat2_dma_prep_memcpy(dma_addr_t dma_dest, dma_addr_t dma_src, size_t len, - int int_en) + unsigned long flags) { struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);struct ioat_desc_sw *new;
drivers/dma/iop-adma.c +10 -10
@@ -537,7 +537,7 @@ iop_adma_prep_dma_interrupt(struct dma_chan *chan)static struct dma_async_tx_descriptor *iop_adma_prep_dma_memcpy (struct dma_chan *chan,dma_addr_t dma_dest, -dma_addr_t dma_src,size_t len,int int_en) +dma_addr_t dma_src,size_t len,unsigned long flags) {struct iop_adma_chan *iop_chan =to_iop_adma_chan (chan);struct iop_adma_desc_slot *sw_desc, *grp_start;
@@ -555,7 +555,7 @@ iop_adma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dma_dest, sw_desc =iop_adma_alloc_slots (iop_chan, slot_cnt, slots_per_op);if (sw_desc) { grp_start = sw_desc->group_head; -iop_desc_init_memcpy (grp_start, int_en); +iop_desc_init_memcpy (grp_start, flags);iop_desc_set_byte_count (grp_start, iop_chan, len);iop_desc_set_dest_addr (grp_start, iop_chan, dma_dest);iop_desc_set_memcpy_src_addr (grp_start, dma_src);
@@ -569,7 +569,7 @@ iop_adma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dma_dest,static struct dma_async_tx_descriptor *iop_adma_prep_dma_memset (struct dma_chan *chan,dma_addr_t dma_dest, -int value,size_t len,int int_en) +int value,size_t len,unsigned long flags) {struct iop_adma_chan *iop_chan =to_iop_adma_chan (chan);struct iop_adma_desc_slot *sw_desc, *grp_start;
@@ -587,7 +587,7 @@ iop_adma_prep_dma_memset(struct dma_chan *chan, dma_addr_t dma_dest, sw_desc =iop_adma_alloc_slots (iop_chan, slot_cnt, slots_per_op);if (sw_desc) { grp_start = sw_desc->group_head; -iop_desc_init_memset (grp_start, int_en); +iop_desc_init_memset (grp_start, flags);iop_desc_set_byte_count (grp_start, iop_chan, len);iop_desc_set_block_fill_val (grp_start, value);iop_desc_set_dest_addr (grp_start, iop_chan, dma_dest);
@@ -602,7 +602,7 @@ iop_adma_prep_dma_memset(struct dma_chan *chan, dma_addr_t dma_dest,static struct dma_async_tx_descriptor *iop_adma_prep_dma_xor (struct dma_chan *chan,dma_addr_t dma_dest,dma_addr_t *dma_src,unsigned int src_cnt,size_t len, -int int_en) +unsigned long flags) {struct iop_adma_chan *iop_chan =to_iop_adma_chan (chan);struct iop_adma_desc_slot *sw_desc, *grp_start;
@@ -613,15 +613,15 @@ iop_adma_prep_dma_xor(struct dma_chan *chan, dma_addr_t dma_dest,BUG_ON (unlikely (len >IOP_ADMA_XOR_MAX_BYTE_COUNT ));dev_dbg (iop_chan->device->common.dev, -"%s src_cnt: %d len: %u int_en: %d\n" , - __FUNCTION__, src_cnt, len, int_en); +"%s src_cnt: %d len: %u flags: %lx\n" , + __FUNCTION__, src_cnt, len, flags);spin_lock_bh (&iop_chan->lock); slot_cnt =iop_chan_xor_slot_count (len, src_cnt, &slots_per_op); sw_desc =iop_adma_alloc_slots (iop_chan, slot_cnt, slots_per_op);if (sw_desc) { grp_start = sw_desc->group_head; -iop_desc_init_xor (grp_start, src_cnt, int_en); +iop_desc_init_xor (grp_start, src_cnt, flags);iop_desc_set_byte_count (grp_start, iop_chan, len);iop_desc_set_dest_addr (grp_start, iop_chan, dma_dest); sw_desc->unmap_src_cnt = src_cnt;
@@ -638,7 +638,7 @@ iop_adma_prep_dma_xor(struct dma_chan *chan, dma_addr_t dma_dest,static struct dma_async_tx_descriptor *iop_adma_prep_dma_zero_sum (struct dma_chan *chan,dma_addr_t *dma_src,unsigned int src_cnt,size_t len,u32 *result, -int int_en) +unsigned long flags) {struct iop_adma_chan *iop_chan =to_iop_adma_chan (chan);struct iop_adma_desc_slot *sw_desc, *grp_start;
@@ -655,7 +655,7 @@ iop_adma_prep_dma_zero_sum(struct dma_chan *chan, dma_addr_t *dma_src, sw_desc =iop_adma_alloc_slots (iop_chan, slot_cnt, slots_per_op);if (sw_desc) { grp_start = sw_desc->group_head; -iop_desc_init_zero_sum (grp_start, src_cnt, int_en); +iop_desc_init_zero_sum (grp_start, src_cnt, flags);iop_desc_set_zero_sum_byte_count (grp_start, len); grp_start->xor_check_result = result; pr_debug("\t%s: grp_start->xor_check_result: %p\n",
include/asm-arm/arch-iop13xx/adma.h +10 -8
@@ -247,7 +247,7 @@ static inline u32 iop_desc_get_src_count(struct iop_adma_desc_slot *desc, }static inline void -iop_desc_init_memcpy (struct iop_adma_desc_slot *desc,int int_en) +iop_desc_init_memcpy (struct iop_adma_desc_slot *desc,unsigned long flags) {struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;union {
@@ -257,13 +257,13 @@ iop_desc_init_memcpy(struct iop_adma_desc_slot *desc, int int_en) u_desc_ctrl.value =0 ; u_desc_ctrl.field.xfer_dir =3 ;/* local to internal bus */ - u_desc_ctrl.field.int_en = int_en; + u_desc_ctrl.field.int_en = flags &DMA_PREP_INTERRUPT ; hw_desc->desc_ctrl = u_desc_ctrl.value; hw_desc->crc_addr =0 ; }static inline void -iop_desc_init_memset (struct iop_adma_desc_slot *desc,int int_en) +iop_desc_init_memset (struct iop_adma_desc_slot *desc,unsigned long flags) {struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;union {
@@ -274,14 +274,15 @@ iop_desc_init_memset(struct iop_adma_desc_slot *desc, int int_en) u_desc_ctrl.value =0 ; u_desc_ctrl.field.xfer_dir =3 ;/* local to internal bus */ u_desc_ctrl.field.block_fill_en =1 ; - u_desc_ctrl.field.int_en = int_en; + u_desc_ctrl.field.int_en = flags &DMA_PREP_INTERRUPT ; hw_desc->desc_ctrl = u_desc_ctrl.value; hw_desc->crc_addr =0 ; }/* to do: support buffers larger than ADMA_MAX_BYTE_COUNT */ static inline void -iop_desc_init_xor (struct iop_adma_desc_slot *desc,int src_cnt,int int_en) +iop_desc_init_xor (struct iop_adma_desc_slot *desc,int src_cnt, +unsigned long flags) {struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;union {
@@ -292,7 +293,7 @@ iop_desc_init_xor(struct iop_adma_desc_slot *desc, int src_cnt, int int_en) u_desc_ctrl.value =0 ; u_desc_ctrl.field.src_select = src_cnt -1 ; u_desc_ctrl.field.xfer_dir =3 ;/* local to internal bus */ - u_desc_ctrl.field.int_en = int_en; + u_desc_ctrl.field.int_en = flags &DMA_PREP_INTERRUPT ; hw_desc->desc_ctrl = u_desc_ctrl.value; hw_desc->crc_addr =0 ;
@@ -301,7 +302,8 @@ iop_desc_init_xor(struct iop_adma_desc_slot *desc, int src_cnt, int int_en)/* to do: support buffers larger than ADMA_MAX_BYTE_COUNT */ static inline int -iop_desc_init_zero_sum (struct iop_adma_desc_slot *desc,int src_cnt,int int_en) +iop_desc_init_zero_sum (struct iop_adma_desc_slot *desc,int src_cnt, +unsigned long flags) {struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;union {
@@ -314,7 +316,7 @@ iop_desc_init_zero_sum(struct iop_adma_desc_slot *desc, int src_cnt, int int_en) u_desc_ctrl.field.xfer_dir =3 ;/* local to internal bus */ u_desc_ctrl.field.zero_result =1 ; u_desc_ctrl.field.status_write_back_en =1 ; - u_desc_ctrl.field.int_en = int_en; + u_desc_ctrl.field.int_en = flags &DMA_PREP_INTERRUPT ; hw_desc->desc_ctrl = u_desc_ctrl.value; hw_desc->crc_addr =0 ;
include/asm-arm/hardware/iop3xx-adma.h +17 -13
@@ -414,7 +414,7 @@ static inline void iop3xx_aau_desc_set_src_addr(struct iop3xx_desc_aau *hw_desc, }static inline void -iop_desc_init_memcpy (struct iop_adma_desc_slot *desc,int int_en) +iop_desc_init_memcpy (struct iop_adma_desc_slot *desc,unsigned long flags) {struct iop3xx_desc_dma *hw_desc = desc->hw_desc;union {
@@ -425,14 +425,14 @@ iop_desc_init_memcpy(struct iop_adma_desc_slot *desc, int int_en) u_desc_ctrl.value =0 ; u_desc_ctrl.field.mem_to_mem_en =1 ; u_desc_ctrl.field.pci_transaction =0xe ;/* memory read block */ - u_desc_ctrl.field.int_en = int_en; + u_desc_ctrl.field.int_en = flags &DMA_PREP_INTERRUPT ; hw_desc->desc_ctrl = u_desc_ctrl.value; hw_desc->upper_pci_src_addr =0 ; hw_desc->crc_addr =0 ; }static inline void -iop_desc_init_memset (struct iop_adma_desc_slot *desc,int int_en) +iop_desc_init_memset (struct iop_adma_desc_slot *desc,unsigned long flags) {struct iop3xx_desc_aau *hw_desc = desc->hw_desc;union {
@@ -443,12 +443,13 @@ iop_desc_init_memset(struct iop_adma_desc_slot *desc, int int_en) u_desc_ctrl.value =0 ; u_desc_ctrl.field.blk1_cmd_ctrl =0x2 ;/* memory block fill */ u_desc_ctrl.field.dest_write_en =1 ; - u_desc_ctrl.field.int_en = int_en; + u_desc_ctrl.field.int_en = flags &DMA_PREP_INTERRUPT ; hw_desc->desc_ctrl = u_desc_ctrl.value; }static inline u32 -iop3xx_desc_init_xor (struct iop3xx_desc_aau *hw_desc,int src_cnt,int int_en) +iop3xx_desc_init_xor (struct iop3xx_desc_aau *hw_desc,int src_cnt, +unsigned long flags) {int i, shift;u32 edcr;
@@ -509,21 +510,23 @@ iop3xx_desc_init_xor(struct iop3xx_desc_aau *hw_desc, int src_cnt, int int_en) u_desc_ctrl.field.dest_write_en =1 ; u_desc_ctrl.field.blk1_cmd_ctrl =0x7 ;/* direct fill */ - u_desc_ctrl.field.int_en = int_en; + u_desc_ctrl.field.int_en = flags &DMA_PREP_INTERRUPT ; hw_desc->desc_ctrl = u_desc_ctrl.value;return u_desc_ctrl.value; }static inline void -iop_desc_init_xor (struct iop_adma_desc_slot *desc,int src_cnt,int int_en) +iop_desc_init_xor (struct iop_adma_desc_slot *desc,int src_cnt, +unsigned long flags) { -iop3xx_desc_init_xor (desc->hw_desc, src_cnt, int_en); +iop3xx_desc_init_xor (desc->hw_desc, src_cnt, flags); }/* return the number of operations */ static inline int -iop_desc_init_zero_sum (struct iop_adma_desc_slot *desc,int src_cnt,int int_en) +iop_desc_init_zero_sum (struct iop_adma_desc_slot *desc,int src_cnt, +unsigned long flags) {int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op;struct iop3xx_desc_aau *hw_desc, *prev_hw_desc, *iter;
@@ -538,10 +541,10 @@ iop_desc_init_zero_sum(struct iop_adma_desc_slot *desc, int src_cnt, int int_en)for (i =0 , j =0 ; (slot_cnt -= slots_per_op) >=0 ; i += slots_per_op, j++) { iter =iop_hw_desc_slot_idx (hw_desc, i); - u_desc_ctrl.value =iop3xx_desc_init_xor (iter, src_cnt, int_en); + u_desc_ctrl.value =iop3xx_desc_init_xor (iter, src_cnt, flags); u_desc_ctrl.field.dest_write_en =0 ; u_desc_ctrl.field.zero_result_en =1 ; - u_desc_ctrl.field.int_en = int_en; + u_desc_ctrl.field.int_en = flags &DMA_PREP_INTERRUPT ; iter->desc_ctrl = u_desc_ctrl.value;/* for the subsequent descriptors preserve the store queue
@@ -559,7 +562,8 @@ iop_desc_init_zero_sum(struct iop_adma_desc_slot *desc, int src_cnt, int int_en) }static inline void -iop_desc_init_null_xor (struct iop_adma_desc_slot *desc,int src_cnt,int int_en) +iop_desc_init_null_xor (struct iop_adma_desc_slot *desc,int src_cnt, +unsigned long flags) {struct iop3xx_desc_aau *hw_desc = desc->hw_desc;union {
@@ -591,7 +595,7 @@ iop_desc_init_null_xor(struct iop_adma_desc_slot *desc, int src_cnt, int int_en) } u_desc_ctrl.field.dest_write_en =0 ; - u_desc_ctrl.field.int_en = int_en; + u_desc_ctrl.field.int_en = flags &DMA_PREP_INTERRUPT ; hw_desc->desc_ctrl = u_desc_ctrl.value; }
include/linux/dmaengine.h +13 -4
@@ -95,6 +95,15 @@ enum dma_transaction_type {#define DMA_TX_TYPE_END (DMA_INTERRUPT + 1)/** +* enum dma_prep_flags - DMA flags to augment operation preparation +* @DMA_PREP_INTERRUPT - trigger an interrupt (callback) upon completion of +* this transaction +*/ +enum dma_prep_flags { +DMA_PREP_INTERRUPT = (1 <<0 ), +}; + +/** * dma_cap_mask_t - capabilities bitmap modeled after cpumask_t. * See linux/cpumask.h */
@@ -274,16 +283,16 @@ struct dma_device {struct dma_async_tx_descriptor *(*device_prep_dma_memcpy)(struct dma_chan *chan,dma_addr_t dest,dma_addr_t src, -size_t len,int int_en); +size_t len,unsigned long flags);struct dma_async_tx_descriptor *(*device_prep_dma_xor)(struct dma_chan *chan,dma_addr_t dest,dma_addr_t *src, -unsigned int src_cnt,size_t len,int int_en); +unsigned int src_cnt,size_t len,unsigned long flags);struct dma_async_tx_descriptor *(*device_prep_dma_zero_sum)(struct dma_chan *chan,dma_addr_t *src,unsigned int src_cnt, -size_t len,u32 *result,int int_en); +size_t len,u32 *result,unsigned long flags);struct dma_async_tx_descriptor *(*device_prep_dma_memset)(struct dma_chan *chan,dma_addr_t dest,int value,size_t len, -int int_en); +unsigned long flags);struct dma_async_tx_descriptor *(*device_prep_dma_interrupt)(struct dma_chan *chan);
RE: [PATCH 3/4] async_tx: replace 'int_en' with operation preparationflags
Quoted 12 lines
From: Williams, Dan J
Pass a full set of flags to drivers' per-operation 'prep' routines. Currently the only flag passed is
DMA_PREP_INTERRUPT. The expectation is
that arch-specificasync_tx_find_channel()implementations can exploit this
capability to find the best channel for an operation.Signed-off-by Dan Williams <[email protected]>---
Quoted 10 lines
crypto/async_tx/async_memcpy.c | 3 ++- crypto/async_tx/async_memset.c | 3 ++- crypto/async_tx/async_xor.c | 10 ++++++---- drivers/dma/ioat_dma.c | 4 ++-- drivers/dma/iop-adma.c | 20 ++++++++++---------- include/asm-arm/arch-iop13xx/adma.h | 18 ++++++++++-------- include/asm-arm/hardware/iop3xx-adma.h | 30 +++++++++++++++++------------- include/linux/dmaengine.h | 17 +++++++++++++---- 8 files changed, 62 insertions(+), 43 deletions(-)
Yep - this is good. This will allow us to add an interrupt request flag to the transaction request in the future.
Acked by: Shannon Nelson <[email protected]>
RE: [PATCH 3/4] async_tx: replace 'int_en' with operation preparationflags
Quoted 12 lines
From: Williams, Dan J
Pass a full set of flags to drivers' per-operation 'prep' routines. Currently the only flag passed is
DMA_PREP_INTERRUPT. The expectation is
that arch-specificasync_tx_find_channel()implementations can exploit this
capability to find the best channel for an operation.Signed-off-by Dan Williams <[email protected]>---
Quoted 10 lines
crypto/async_tx/async_memcpy.c | 3 ++- crypto/async_tx/async_memset.c | 3 ++- crypto/async_tx/async_xor.c | 10 ++++++---- drivers/dma/ioat_dma.c | 4 ++-- drivers/dma/iop-adma.c | 20 ++++++++++---------- include/asm-arm/arch-iop13xx/adma.h | 18 ++++++++++-------- include/asm-arm/hardware/iop3xx-adma.h | 30 +++++++++++++++++------------- include/linux/dmaengine.h | 17 +++++++++++++---- 8 files changed, 62 insertions(+), 43 deletions(-)
As ioat_dma is not using int_en right now, this change does not impact the driver at the moment and may be definitely useful later.
Maciej Sosnowski
---------------------------------------------------------------------
Intel Technology Poland sp. z o.o.
z siedziba w Gdansku
ul. Slowackiego 173
80-298 Gdansk
Sad Rejonowy Gdansk Polnoc w Gdansku,
VII Wydzial Gospodarczy Krajowego Rejestru Sadowego, numer KRS 101882
NIP 957-07-52-316
Kapital zakladowy 200.000 zl
This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). Any review or distribution by others is strictly prohibited. If you are not the intended recipient, please contact the sender and delete all copies.
PATCH 4/4 async_tx: allow architecture specific async_tx_find_channel implementations
In reply to Dan WilliamsThe source and destination addresses are included to allow channel selection based on address alignment.
---
crypto/async_tx/async_memcpy.c | 3 ++- crypto/async_tx/async_memset.c | 3 ++- crypto/async_tx/async_tx.c | 6 +++--- crypto/async_tx/async_xor.c | 8 ++++++-- include/linux/async_tx.h | 11 +++++++++-- 5 files changed, 22 insertions(+), 9 deletions(-)
crypto/async_tx/async_memcpy.c +2 -1
@@ -46,7 +46,8 @@ async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,struct dma_async_tx_descriptor *depend_tx, dma_async_tx_callback cb_fn, void *cb_param) { - struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_MEMCPY); + struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_MEMCPY, + &dest,1 , &src,1 , len);struct dma_device *device = chan ? chan->device :NULL ;struct dma_async_tx_descriptor *tx =NULL ;
crypto/async_tx/async_memset.c +2 -1
@@ -46,7 +46,8 @@ async_memset(struct page *dest, int val, unsigned int offset,struct dma_async_tx_descriptor *depend_tx, dma_async_tx_callback cb_fn, void *cb_param) { - struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_MEMSET); + struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_MEMSET, + &dest,1 ,NULL ,0 , len);struct dma_device *device = chan ? chan->device :NULL ;struct dma_async_tx_descriptor *tx =NULL ;
crypto/async_tx/async_tx.c +3 -3
@@ -361,13 +361,13 @@ static void __exit async_tx_exit(void) }/** -* async_tx_find_channel - find a channel to carry out the operation or let +* __async_tx_find_channel - find a channel to carry out the operation or let * the transaction execute synchronously * @depend_tx: transaction dependency * @tx_type: transaction type */ struct dma_chan * -async_tx_find_channel (struct dma_async_tx_descriptor *depend_tx, +__async_tx_find_channel (struct dma_async_tx_descriptor *depend_tx,enum dma_transaction_type tx_type) {/* see if we can keep the chain on one channel */
@@ -383,7 +383,7 @@ async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx, } elsereturn NULL ; } -EXPORT_SYMBOL_GPL (async_tx_find_channel); +EXPORT_SYMBOL_GPL (__async_tx_find_channel);#else static int __init async_tx_init (void ) {
crypto/async_tx/async_xor.c +6 -2
@@ -125,7 +125,9 @@ async_xor(struct page *dest, struct page **src_list, unsigned int offset,struct dma_async_tx_descriptor *depend_tx, dma_async_tx_callback cb_fn, void *cb_param) { - struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_XOR); + struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_XOR, + &dest,1 , src_list, + src_cnt, len);struct dma_device *device = chan ? chan->device :NULL ;struct dma_async_tx_descriptor *tx =NULL ;dma_async_tx_callback _cb_fn;
@@ -257,7 +259,9 @@ async_xor_zero_sum(struct page *dest, struct page **src_list,struct dma_async_tx_descriptor *depend_tx, dma_async_tx_callback cb_fn, void *cb_param) { - struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_ZERO_SUM); + struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_ZERO_SUM, + &dest,1 , src_list, + src_cnt, len);struct dma_device *device = chan ? chan->device :NULL ;struct dma_async_tx_descriptor *tx =NULL ;
include/linux/async_tx.h +9 -2
@@ -62,9 +62,15 @@ enum async_tx_flags {void async_tx_issue_pending_all (void );enum dma_status dma_wait_for_async_tx (struct dma_async_tx_descriptor *tx);void async_tx_run_dependencies (struct dma_async_tx_descriptor *tx); +#ifdef CONFIG_ARCH_HAS_ASYNC_TX_FIND_CHANNEL +#include <asm/async_tx.h> +#else +#define async_tx_find_channel (dep, type, dst, dst_count, src, src_count, len) \ + __async_tx_find_channel(dep, type)struct dma_chan * -async_tx_find_channel (struct dma_async_tx_descriptor *depend_tx, +__async_tx_find_channel (struct dma_async_tx_descriptor *depend_tx,enum dma_transaction_type tx_type); +#endif /* CONFIG_ARCH_HAS_ASYNC_TX_FIND_CHANNEL */ #else static inline void async_tx_issue_pending_all (void ) {
@@ -86,7 +92,8 @@ async_tx_run_dependencies(struct dma_async_tx_descriptor *tx,static inline struct dma_chan *async_tx_find_channel (struct dma_async_tx_descriptor *depend_tx, -enum dma_transaction_type tx_type) +enum dma_transaction_type tx_type,struct page **dst,int dst_count, +struct page **src,int src_count,size_t len) {return NULL ; }