Commit e817ee5f authored by Christoph Hellwig's avatar Christoph Hellwig

dma-iommu: implement ->alloc_noncontiguous

Implement support for allocating a non-contiguous DMA region.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarTomasz Figa <tfiga@chromium.org>
Tested-by: default avatarRicardo Ribalda <ribalda@chromium.org>
parent 8230ce9a
...@@ -708,6 +708,7 @@ static struct page **__iommu_dma_alloc_noncontiguous(struct device *dev, ...@@ -708,6 +708,7 @@ static struct page **__iommu_dma_alloc_noncontiguous(struct device *dev,
goto out_free_sg; goto out_free_sg;
sgt->sgl->dma_address = iova; sgt->sgl->dma_address = iova;
sgt->sgl->dma_length = size;
return pages; return pages;
out_free_sg: out_free_sg:
...@@ -745,6 +746,37 @@ static void *iommu_dma_alloc_remap(struct device *dev, size_t size, ...@@ -745,6 +746,37 @@ static void *iommu_dma_alloc_remap(struct device *dev, size_t size,
return NULL; return NULL;
} }
#ifdef CONFIG_DMA_REMAP
static struct sg_table *iommu_dma_alloc_noncontiguous(struct device *dev,
size_t size, enum dma_data_direction dir, gfp_t gfp,
unsigned long attrs)
{
struct dma_sgt_handle *sh;
sh = kmalloc(sizeof(*sh), gfp);
if (!sh)
return NULL;
sh->pages = __iommu_dma_alloc_noncontiguous(dev, size, &sh->sgt, gfp,
PAGE_KERNEL, attrs);
if (!sh->pages) {
kfree(sh);
return NULL;
}
return &sh->sgt;
}
static void iommu_dma_free_noncontiguous(struct device *dev, size_t size,
struct sg_table *sgt, enum dma_data_direction dir)
{
struct dma_sgt_handle *sh = sgt_handle(sgt);
__iommu_dma_unmap(dev, sgt->sgl->dma_address, size);
__iommu_dma_free_pages(sh->pages, PAGE_ALIGN(size) >> PAGE_SHIFT);
sg_free_table(&sh->sgt);
}
#endif /* CONFIG_DMA_REMAP */
static void iommu_dma_sync_single_for_cpu(struct device *dev, static void iommu_dma_sync_single_for_cpu(struct device *dev,
dma_addr_t dma_handle, size_t size, enum dma_data_direction dir) dma_addr_t dma_handle, size_t size, enum dma_data_direction dir)
{ {
...@@ -1261,6 +1293,10 @@ static const struct dma_map_ops iommu_dma_ops = { ...@@ -1261,6 +1293,10 @@ static const struct dma_map_ops iommu_dma_ops = {
.free = iommu_dma_free, .free = iommu_dma_free,
.alloc_pages = dma_common_alloc_pages, .alloc_pages = dma_common_alloc_pages,
.free_pages = dma_common_free_pages, .free_pages = dma_common_free_pages,
#ifdef CONFIG_DMA_REMAP
.alloc_noncontiguous = iommu_dma_alloc_noncontiguous,
.free_noncontiguous = iommu_dma_free_noncontiguous,
#endif
.mmap = iommu_dma_mmap, .mmap = iommu_dma_mmap,
.get_sgtable = iommu_dma_get_sgtable, .get_sgtable = iommu_dma_get_sgtable,
.map_page = iommu_dma_map_page, .map_page = iommu_dma_map_page,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment