From 9ae4a416cf931d24714e96de53cb5bd4a5c9414f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 8 Dec 2008 13:46:00 -0700 Subject: async_xor: dma_map destination DMA_BIDIRECTIONAL 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: Cc: Saeed Bishara Acked-by: Yuri Tikhonov Signed-off-by: Dan Williams --- crypto/async_tx/async_xor.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'crypto/async_tx') diff --git a/crypto/async_tx/async_xor.c b/crypto/async_tx/async_xor.c index c029d3eb..595b7867 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; -- cgit v1.2.3