summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_gem_cma_helper.c
diff options
context:
space:
mode:
authorLiviu Dudau <Liviu.Dudau@arm.com>2017-11-10 13:33:10 +0000
committerNoralf Trønnes <noralf@tronnes.org>2017-11-15 18:14:46 +0100
commit998fb1a0f478b83492220ff79583bf9ad538bdd8 (patch)
tree2726e7460e19dbee07402dec75f13522b44c6502 /drivers/gpu/drm/drm_gem_cma_helper.c
parent1f2d9bdc9085a4477a997344b17c40ba2a28d4e4 (diff)
downloadlinux-998fb1a0f478b83492220ff79583bf9ad538bdd8.tar.bz2
drm: gem_cma_helper.c: Allow importing of contiguous scatterlists with nents > 1
drm_gem_cma_prime_import_sg_table() will fail if the number of entries in the sg_table > 1. However, you can have a device that uses an IOMMU engine and can map a discontiguous buffer with multiple entries that have consecutive sg_dma_addresses, effectively making it contiguous. Allow for that scenario by testing the entries in the sg_table for contiguous coverage. Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Liviu Dudau <liviu.dudau@arm.com> Signed-off-by: Noralf Trønnes <noralf@tronnes.org> Link: https://patchwork.freedesktop.org/patch/msgid/20171110133310.1225-1-Liviu.Dudau@arm.com
Diffstat (limited to 'drivers/gpu/drm/drm_gem_cma_helper.c')
-rw-r--r--drivers/gpu/drm/drm_gem_cma_helper.c22
1 files changed, 20 insertions, 2 deletions
diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c b/drivers/gpu/drm/drm_gem_cma_helper.c
index ce67d7d42c66..80a5115c3846 100644
--- a/drivers/gpu/drm/drm_gem_cma_helper.c
+++ b/drivers/gpu/drm/drm_gem_cma_helper.c
@@ -475,8 +475,26 @@ drm_gem_cma_prime_import_sg_table(struct drm_device *dev,
{
struct drm_gem_cma_object *cma_obj;
- if (sgt->nents != 1)
- return ERR_PTR(-EINVAL);
+ if (sgt->nents != 1) {
+ /* check if the entries in the sg_table are contiguous */
+ dma_addr_t next_addr = sg_dma_address(sgt->sgl);
+ struct scatterlist *s;
+ unsigned int i;
+
+ for_each_sg(sgt->sgl, s, sgt->nents, i) {
+ /*
+ * sg_dma_address(s) is only valid for entries
+ * that have sg_dma_len(s) != 0
+ */
+ if (!sg_dma_len(s))
+ continue;
+
+ if (sg_dma_address(s) != next_addr)
+ return ERR_PTR(-EINVAL);
+
+ next_addr = sg_dma_address(s) + sg_dma_len(s);
+ }
+ }
/* Create a CMA GEM buffer. */
cma_obj = __drm_gem_cma_create(dev, attach->dmabuf->size);