aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/iop-adma.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/dma/iop-adma.c')
-rw-r--r--drivers/dma/iop-adma.c27
1 files changed, 19 insertions, 8 deletions
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
index 71fba82462cb..6be317262200 100644
--- a/drivers/dma/iop-adma.c
+++ b/drivers/dma/iop-adma.c
@@ -85,18 +85,28 @@ iop_adma_run_tx_complete_actions(struct iop_adma_desc_slot *desc,
85 enum dma_ctrl_flags flags = desc->async_tx.flags; 85 enum dma_ctrl_flags flags = desc->async_tx.flags;
86 u32 src_cnt; 86 u32 src_cnt;
87 dma_addr_t addr; 87 dma_addr_t addr;
88 dma_addr_t dest;
88 89
90 src_cnt = unmap->unmap_src_cnt;
91 dest = iop_desc_get_dest_addr(unmap, iop_chan);
89 if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP)) { 92 if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
90 addr = iop_desc_get_dest_addr(unmap, iop_chan); 93 enum dma_data_direction dir;
91 dma_unmap_page(dev, addr, len, DMA_FROM_DEVICE); 94
95 if (src_cnt > 1) /* is xor? */
96 dir = DMA_BIDIRECTIONAL;
97 else
98 dir = DMA_FROM_DEVICE;
99
100 dma_unmap_page(dev, dest, len, dir);
92 } 101 }
93 102
94 if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) { 103 if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
95 src_cnt = unmap->unmap_src_cnt;
96 while (src_cnt--) { 104 while (src_cnt--) {
97 addr = iop_desc_get_src_addr(unmap, 105 addr = iop_desc_get_src_addr(unmap,
98 iop_chan, 106 iop_chan,
99 src_cnt); 107 src_cnt);
108 if (addr == dest)
109 continue;
100 dma_unmap_page(dev, addr, len, 110 dma_unmap_page(dev, addr, len,
101 DMA_TO_DEVICE); 111 DMA_TO_DEVICE);
102 } 112 }
@@ -411,6 +421,7 @@ iop_adma_tx_submit(struct dma_async_tx_descriptor *tx)
411 int slot_cnt; 421 int slot_cnt;
412 int slots_per_op; 422 int slots_per_op;
413 dma_cookie_t cookie; 423 dma_cookie_t cookie;
424 dma_addr_t next_dma;
414 425
415 grp_start = sw_desc->group_head; 426 grp_start = sw_desc->group_head;
416 slot_cnt = grp_start->slot_cnt; 427 slot_cnt = grp_start->slot_cnt;
@@ -425,12 +436,12 @@ iop_adma_tx_submit(struct dma_async_tx_descriptor *tx)
425 &old_chain_tail->chain_node); 436 &old_chain_tail->chain_node);
426 437
427 /* fix up the hardware chain */ 438 /* fix up the hardware chain */
428 iop_desc_set_next_desc(old_chain_tail, grp_start->async_tx.phys); 439 next_dma = grp_start->async_tx.phys;
440 iop_desc_set_next_desc(old_chain_tail, next_dma);
441 BUG_ON(iop_desc_get_next_desc(old_chain_tail) != next_dma); /* flush */
429 442
430 /* 1/ don't add pre-chained descriptors 443 /* check for pre-chained descriptors */
431 * 2/ dummy read to flush next_desc write 444 iop_paranoia(iop_desc_get_next_desc(sw_desc));
432 */
433 BUG_ON(iop_desc_get_next_desc(sw_desc));
434 445
435 /* increment the pending count by the number of slots 446 /* increment the pending count by the number of slots
436 * memcpy operations have a 1:1 (slot:operation) relation 447 * memcpy operations have a 1:1 (slot:operation) relation