summaryrefslogtreecommitdiff
path: root/crypto
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2008-12-08 13:46:00 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2009-01-14 09:44:03 -0800
commitcf7af4a82fe408a8c9628480ac3dc272e087ce75 (patch)
tree2bbcd39200e386232a266e39b0d9bda5d40bd674 /crypto
parent65e8fedf5e9d81cce3505a4dfce77096eac89711 (diff)
async_xor: dma_map destination DMA_BIDIRECTIONAL
commit a06d568f7c5e40e34ea64881842deb8f4382babf upstream. Mapping the destination multiple times is a misuse of the dma-api. Since the destination may be reused as a source, ensure that it is only mapped once and that it is mapped bidirectionally. This appears to add ugliness on the unmap side in that it always reads back the destination address from the descriptor, but gcc can determine that dma_unmap is a nop and not emit the code that calculates its arguments. Cc: Saeed Bishara <saeed@marvell.com> Acked-by: Yuri Tikhonov <yur@emcraft.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'crypto')
-rw-r--r--crypto/async_tx/async_xor.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/crypto/async_tx/async_xor.c b/crypto/async_tx/async_xor.c
index c029d3eb9ef0..595b78672b36 100644
--- a/crypto/async_tx/async_xor.c
+++ b/crypto/async_tx/async_xor.c
@@ -53,10 +53,17 @@ do_async_xor(struct dma_chan *chan, struct page *dest, struct page **src_list,
int xor_src_cnt;
dma_addr_t dma_dest;
- dma_dest = dma_map_page(dma->dev, dest, offset, len, DMA_FROM_DEVICE);
- for (i = 0; i < src_cnt; i++)
+ /* map the dest bidrectional in case it is re-used as a source */
+ dma_dest = dma_map_page(dma->dev, dest, offset, len, DMA_BIDIRECTIONAL);
+ for (i = 0; i < src_cnt; i++) {
+ /* only map the dest once */
+ if (unlikely(src_list[i] == dest)) {
+ dma_src[i] = dma_dest;
+ continue;
+ }
dma_src[i] = dma_map_page(dma->dev, src_list[i], offset,
len, DMA_TO_DEVICE);
+ }
while (src_cnt) {
async_flags = flags;