async_xor: dma_map destination DMA_BIDIRECTIONAL
[linux-2.6.git] / drivers / dma / iop-adma.c
index c7a9306d951d2c61f622c601ef2d49af422b679e..6be3172622009ff67ec502b049f167d6ccebe1cd 100644 (file)
@@ -85,18 +85,28 @@ iop_adma_run_tx_complete_actions(struct iop_adma_desc_slot *desc,
                        enum dma_ctrl_flags flags = desc->async_tx.flags;
                        u32 src_cnt;
                        dma_addr_t addr;
+                       dma_addr_t dest;
 
+                       src_cnt = unmap->unmap_src_cnt;
+                       dest = iop_desc_get_dest_addr(unmap, iop_chan);
                        if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
-                               addr = iop_desc_get_dest_addr(unmap, iop_chan);
-                               dma_unmap_page(dev, addr, len, DMA_FROM_DEVICE);
+                               enum dma_data_direction dir;
+
+                               if (src_cnt > 1) /* is xor? */
+                                       dir = DMA_BIDIRECTIONAL;
+                               else
+                                       dir = DMA_FROM_DEVICE;
+
+                               dma_unmap_page(dev, dest, len, dir);
                        }
 
                        if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
-                               src_cnt = unmap->unmap_src_cnt;
                                while (src_cnt--) {
                                        addr = iop_desc_get_src_addr(unmap,
                                                                     iop_chan,
                                                                     src_cnt);
+                                       if (addr == dest)
+                                               continue;
                                        dma_unmap_page(dev, addr, len,
                                                       DMA_TO_DEVICE);
                                }