This provides support to unmap scatterlist with the
dmaengine_unmap_data. We will support only 1 scatterlist per
direction.

Signed-off-by: Dave Jiang <dave.ji...@intel.com>
---
 drivers/dma/dmaengine.c   |   27 +++++++++++++++++++++++++++
 include/linux/dmaengine.h |   13 ++++++++++++-
 2 files changed, 39 insertions(+), 1 deletion(-)

diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 40a035e..09ee03d 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -1124,12 +1124,39 @@ static struct dmaengine_unmap_pool 
*__get_unmap_pool(int nr)
        }
 }
 
+static void dmaengine_unmap_sg(struct dmaengine_unmap_data *unmap)
+{
+       struct device *dev = unmap->dev;
+
+       if (unmap->to_sg) {
+               dma_unmap_sg(dev, unmap->unmap_sg.sg,
+                               unmap->sg_nents, DMA_TO_DEVICE);
+
+               dma_unmap_page(dev, unmap->unmap_sg.buf_phys, unmap->len,
+                                       DMA_FROM_DEVICE);
+       }
+
+       if (unmap->from_sg) {
+               dma_unmap_page(dev, unmap->unmap_sg.buf_phys, unmap->len,
+                               DMA_TO_DEVICE);
+               dma_unmap_sg(dev, unmap->unmap_sg.sg,
+                               unmap->sg_nents, DMA_FROM_DEVICE);
+       }
+
+       mempool_free(unmap, __get_unmap_pool(unmap->map_cnt)->pool);
+}
+
 static void dmaengine_unmap(struct kref *kref)
 {
        struct dmaengine_unmap_data *unmap = container_of(kref, typeof(*unmap), 
kref);
        struct device *dev = unmap->dev;
        int cnt, i;
 
+       if (unmap->to_sg || unmap->from_sg) {
+               dmaengine_unmap_sg(unmap);
+               return;
+       }
+
        cnt = unmap->to_cnt;
        for (i = 0; i < cnt; i++)
                dma_unmap_page(dev, unmap->addr[i], unmap->len,
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index 53356c4..fc53854 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -464,15 +464,26 @@ struct dmaengine_result {
 typedef void (*dma_async_tx_callback_result)(void *dma_async_param,
                                const struct dmaengine_result *result);
 
+struct dmaengine_unmap_sg {
+       struct scatterlist *sg;
+       dma_addr_t buf_phys;
+};
+
 struct dmaengine_unmap_data {
        u8 map_cnt;
        u8 to_cnt;
+       u8 to_sg;
        u8 from_cnt;
+       u8 from_sg;
        u8 bidi_cnt;
+       int sg_nents;
        struct device *dev;
        struct kref kref;
        size_t len;
-       dma_addr_t addr[0];
+       union {
+               struct dmaengine_unmap_sg unmap_sg;
+               dma_addr_t addr[0];
+       };
 };
 
 /**

_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

Reply via email to