media: vb2-dma-contig: add helper for setting dma max seg size

Add a helper function for device drivers to set DMA's max_seg_size.
Setting it to largest possible value lets DMA-mapping API always create
contiguous mappings in DMA address space. This is essential for all
devices, which use dma-contig videobuf2 memory allocator and shared
buffers.

Till now, the only case when vb2-dma-contig really 'worked' was a case
where userspace provided USERPTR buffer, which was in fact mmaped
contiguous buffer from the other v4l2/drm device. Also DMABUF made of
contiguous buffer worked only when its exporter did not split it into
several chunks in the scatter-list. Any other buffer failed, regardless
of the arch/platform used and the presence of the IOMMU of the device bus.

This patch provides interface to fix this issue.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
This commit is contained in:
Marek Szyprowski 2016-05-24 09:16:06 +02:00 committed by Sylwester Nawrocki
parent c974c436ea
commit 3f03396918
2 changed files with 55 additions and 0 deletions

View file

@ -753,6 +753,59 @@ void vb2_dma_contig_cleanup_ctx(void *alloc_ctx)
}
EXPORT_SYMBOL_GPL(vb2_dma_contig_cleanup_ctx);
/**
* vb2_dma_contig_set_max_seg_size() - configure DMA max segment size
* @dev: device for configuring DMA parameters
* @size: size of DMA max segment size to set
*
* To allow mapping the scatter-list into a single chunk in the DMA
* address space, the device is required to have the DMA max segment
* size parameter set to a value larger than the buffer size. Otherwise,
* the DMA-mapping subsystem will split the mapping into max segment
* size chunks. This function sets the DMA max segment size
* parameter to let DMA-mapping map a buffer as a single chunk in DMA
* address space.
* This code assumes that the DMA-mapping subsystem will merge all
* scatterlist segments if this is really possible (for example when
* an IOMMU is available and enabled).
* Ideally, this parameter should be set by the generic bus code, but it
* is left with the default 64KiB value due to historical litmiations in
* other subsystems (like limited USB host drivers) and there no good
* place to set it to the proper value.
* This function should be called from the drivers, which are known to
* operate on platforms with IOMMU and provide access to shared buffers
* (either USERPTR or DMABUF). This should be done before initializing
* videobuf2 queue.
*/
int vb2_dma_contig_set_max_seg_size(struct device *dev, unsigned int size)
{
if (!dev->dma_parms) {
dev->dma_parms = kzalloc(sizeof(dev->dma_parms), GFP_KERNEL);
if (!dev->dma_parms)
return -ENOMEM;
}
if (dma_get_max_seg_size(dev) < size)
return dma_set_max_seg_size(dev, size);
return 0;
}
EXPORT_SYMBOL_GPL(vb2_dma_contig_set_max_seg_size);
/*
* vb2_dma_contig_clear_max_seg_size() - release resources for DMA parameters
* @dev: device for configuring DMA parameters
*
* This function releases resources allocated to configure DMA parameters
* (see vb2_dma_contig_set_max_seg_size() function). It should be called from
* device drivers on driver remove.
*/
void vb2_dma_contig_clear_max_seg_size(struct device *dev)
{
kfree(dev->dma_parms);
dev->dma_parms = NULL;
}
EXPORT_SYMBOL_GPL(vb2_dma_contig_clear_max_seg_size);
MODULE_DESCRIPTION("DMA-contig memory handling routines for videobuf2");
MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>");
MODULE_LICENSE("GPL");

View file

@ -35,6 +35,8 @@ static inline void *vb2_dma_contig_init_ctx(struct device *dev)
}
void vb2_dma_contig_cleanup_ctx(void *alloc_ctx);
int vb2_dma_contig_set_max_seg_size(struct device *dev, unsigned int size);
void vb2_dma_contig_clear_max_seg_size(struct device *dev);
extern const struct vb2_mem_ops vb2_dma_contig_memops;