@@ -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,
@@ -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];
+ };
};
/**
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.jiang@intel.com> --- drivers/dma/dmaengine.c | 27 +++++++++++++++++++++++++++ include/linux/dmaengine.h | 13 ++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-)