Convert core async_tx code (do_async_gen_syndrome()) to do
DMA unmapping itself using the ->callback functionality.

Cc: Dan Williams <d...@fb.com>
Cc: Tomasz Figa <t.f...@samsung.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnier...@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.p...@samsung.com>
---
 crypto/async_tx/async_pq.c | 90 +++++++++++++++++++++++++++++++++-------------
 include/linux/dmaengine.h  |  2 +-
 2 files changed, 66 insertions(+), 26 deletions(-)

diff --git a/crypto/async_tx/async_pq.c b/crypto/async_tx/async_pq.c
index 91d5d38..2848fe8 100644
--- a/crypto/async_tx/async_pq.c
+++ b/crypto/async_tx/async_pq.c
@@ -42,6 +42,26 @@ static struct page *pq_scribble_page;
 #define P(b, d) (b[d-2])
 #define Q(b, d) (b[d-1])
 
+static void do_async_gen_syndrome_cb(void *dma_async_param)
+{
+       struct dma_async_tx_descriptor *tx = dma_async_param;
+       struct dma_device *dev = tx->chan->device;
+       int i;
+
+       for (i = 0; i < 2; i++) {
+               if (tx->dma_dst[i])
+                       dma_unmap_page(dev->dev, tx->dma_dst[i], tx->dma_len,
+                                      DMA_BIDIRECTIONAL);
+       }
+
+       for (i = 0; i < tx->dma_src_cnt; i++)
+               dma_unmap_page(dev->dev, tx->dma_src[i], tx->dma_len,
+                              DMA_TO_DEVICE);
+
+       if (tx->orig_callback)
+               tx->orig_callback(tx->orig_callback_param);
+}
+
 /**
  * do_async_gen_syndrome - asynchronously calculate P and/or Q
  */
@@ -61,37 +81,21 @@ do_async_gen_syndrome(struct dma_chan *chan, struct page 
**blocks,
        unsigned char coefs[src_cnt];
        unsigned short pq_src_cnt;
        dma_addr_t dma_dest[2];
-       int src_off = 0;
+       int blocks_cnt = 0;
        int idx;
        int i;
 
-       /* DMAs use destinations as sources, so use BIDIRECTIONAL mapping */
-       if (P(blocks, disks))
-               dma_dest[0] = dma_map_page(dma->dev, P(blocks, disks), offset,
-                                          len, DMA_BIDIRECTIONAL);
-       else
-               dma_flags |= DMA_PREP_PQ_DISABLE_P;
-       if (Q(blocks, disks))
-               dma_dest[1] = dma_map_page(dma->dev, Q(blocks, disks), offset,
-                                          len, DMA_BIDIRECTIONAL);
-       else
-               dma_flags |= DMA_PREP_PQ_DISABLE_Q;
-
-       /* convert source addresses being careful to collapse 'empty'
-        * sources and update the coefficients accordingly
-        */
        for (i = 0, idx = 0; i < src_cnt; i++) {
                if (blocks[i] == NULL)
                        continue;
-               dma_src[idx] = dma_map_page(dma->dev, blocks[i], offset, len,
-                                           DMA_TO_DEVICE);
-               coefs[idx] = scfs[i];
                idx++;
        }
        src_cnt = idx;
 
        while (src_cnt > 0) {
                submit->flags = flags_orig;
+               dma_flags = DMA_COMPL_SKIP_SRC_UNMAP |
+                           DMA_COMPL_SKIP_DEST_UNMAP;
                pq_src_cnt = min(src_cnt, dma_maxpq(dma, dma_flags));
                /* if we are submitting additional pqs, leave the chain open,
                 * clear the callback parameters, and leave the destination
@@ -100,11 +104,9 @@ do_async_gen_syndrome(struct dma_chan *chan, struct page 
**blocks,
                if (src_cnt > pq_src_cnt) {
                        submit->flags &= ~ASYNC_TX_ACK;
                        submit->flags |= ASYNC_TX_FENCE;
-                       dma_flags |= DMA_COMPL_SKIP_DEST_UNMAP;
                        submit->cb_fn = NULL;
                        submit->cb_param = NULL;
                } else {
-                       dma_flags &= ~DMA_COMPL_SKIP_DEST_UNMAP;
                        submit->cb_fn = cb_fn_orig;
                        submit->cb_param = cb_param_orig;
                        if (cb_fn_orig)
@@ -113,15 +115,46 @@ do_async_gen_syndrome(struct dma_chan *chan, struct page 
**blocks,
                if (submit->flags & ASYNC_TX_FENCE)
                        dma_flags |= DMA_PREP_FENCE;
 
+               /*
+                * DMAs use destinations as sources,
+                * so use BIDIRECTIONAL mapping
+                */
+               if (P(blocks, disks))
+                       dma_dest[0] = dma_map_page(dma->dev, P(blocks, disks),
+                                               offset, len, DMA_BIDIRECTIONAL);
+               else {
+                       dma_dest[0] = 0;
+                       dma_flags |= DMA_PREP_PQ_DISABLE_P;
+               }
+               if (Q(blocks, disks))
+                       dma_dest[1] = dma_map_page(dma->dev, Q(blocks, disks),
+                                               offset, len, DMA_BIDIRECTIONAL);
+               else {
+                       dma_dest[1] = 0;
+                       dma_flags |= DMA_PREP_PQ_DISABLE_Q;
+               }
+
+               /* convert source addresses being careful to collapse 'empty'
+                * sources and update the coefficients accordingly
+                */
+               for (i = blocks_cnt, idx = 0; idx < pq_src_cnt; i++) {
+                       if (blocks[i] == NULL)
+                               continue;
+                       dma_src[idx] = dma_map_page(dma->dev, blocks[i], offset,
+                                                   len, DMA_TO_DEVICE);
+                       coefs[idx] = scfs[i];
+                       idx++;
+               }
+
                /* Since we have clobbered the src_list we are committed
                 * to doing this asynchronously.  Drivers force forward
                 * progress in case they can not provide a descriptor
                 */
                for (;;) {
                        tx = dma->device_prep_dma_pq(chan, dma_dest,
-                                                    &dma_src[src_off],
+                                                    &dma_src[0],
                                                     pq_src_cnt,
-                                                    &coefs[src_off], len,
+                                                    &coefs[0], len,
                                                     dma_flags);
                        if (likely(tx))
                                break;
@@ -129,12 +162,19 @@ do_async_gen_syndrome(struct dma_chan *chan, struct page 
**blocks,
                        dma_async_issue_pending(chan);
                }
 
-               async_tx_submit(chan, tx, submit);
+               for (i = 0; i < pq_src_cnt; i++)
+                       tx->dma_src[i] = dma_src[i];
+               tx->dma_src_cnt = pq_src_cnt;
+               tx->dma_dst[0] = dma_dest[0];
+               tx->dma_dst[1] = dma_dest[1];
+               tx->dma_len = len;
+
+               __async_tx_submit(chan, tx, do_async_gen_syndrome_cb, tx,
+                                 submit);
                submit->depend_tx = tx;
 
                /* drop completed sources */
                src_cnt -= pq_src_cnt;
-               src_off += pq_src_cnt;
 
                dma_flags |= DMA_PREP_CONTINUE;
        }
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index 0df69f1..af3b941 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -393,7 +393,7 @@ typedef bool (*dma_filter_fn)(struct dma_chan *chan, void 
*filter_param);
 
 typedef void (*dma_async_tx_callback)(void *dma_async_param);
 
-/* max value of ->max_xor from struct dma_device */
+/* max value of ->max_[xor,pq] from struct dma_device */
 #define DMA_ASYNC_TX_MAX_ENT 128
 
 /**
-- 
1.8.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to