From 04c0746663bd3ae3cce5e02d5b32c8ade2a833b8 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 7 Feb 2018 18:45:55 +0100 Subject: drm/tegra: gem: Make __tegra_gem_mmap() available more widely This function allows mapping a GEM object into a virtual memory address space, which makes it useful outside of the GEM code. While at it, rename the function so it doesn't clash with the function that implements the DRM_TEGRA_GEM_MMAP IOCTL. Signed-off-by: Thierry Reding --- drivers/gpu/drm/tegra/gem.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/tegra/gem.c') diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c index 49b9bf28f872..d3b3aa148225 100644 --- a/drivers/gpu/drm/tegra/gem.c +++ b/drivers/gpu/drm/tegra/gem.c @@ -459,8 +459,7 @@ const struct vm_operations_struct tegra_bo_vm_ops = { .close = drm_gem_vm_close, }; -static int tegra_gem_mmap(struct drm_gem_object *gem, - struct vm_area_struct *vma) +int __tegra_gem_mmap(struct drm_gem_object *gem, struct vm_area_struct *vma) { struct tegra_bo *bo = to_tegra_bo(gem); @@ -507,7 +506,7 @@ int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma) gem = vma->vm_private_data; - return tegra_gem_mmap(gem, vma); + return __tegra_gem_mmap(gem, vma); } static struct sg_table * @@ -600,7 +599,7 @@ static int tegra_gem_prime_mmap(struct dma_buf *buf, struct vm_area_struct *vma) if (err < 0) return err; - return tegra_gem_mmap(gem, vma); + return __tegra_gem_mmap(gem, vma); } static void *tegra_gem_prime_vmap(struct dma_buf *buf) -- cgit From bd43c9f0fa1f664b58eefdc8aab7ac3c8b2026ec Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 13 Dec 2017 12:22:48 +0100 Subject: drm/tegra: gem: Map pages via the DMA API When allocating pages, map them with the DMA API in order to invalidate caches. This is the correct usage of the API and works just as well as faking up the SG table and using the dma_sync_sg_for_device() function. Signed-off-by: Thierry Reding --- drivers/gpu/drm/tegra/gem.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers/gpu/drm/tegra/gem.c') diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c index d3b3aa148225..8fc5860ab19a 100644 --- a/drivers/gpu/drm/tegra/gem.c +++ b/drivers/gpu/drm/tegra/gem.c @@ -203,6 +203,8 @@ free: static void tegra_bo_free(struct drm_device *drm, struct tegra_bo *bo) { if (bo->pages) { + dma_unmap_sg(drm->dev, bo->sgt->sgl, bo->sgt->nents, + DMA_BIDIRECTIONAL); drm_gem_put_pages(&bo->gem, bo->pages, true, true); sg_free_table(bo->sgt); kfree(bo->sgt); @@ -213,8 +215,7 @@ static void tegra_bo_free(struct drm_device *drm, struct tegra_bo *bo) static int tegra_bo_get_pages(struct drm_device *drm, struct tegra_bo *bo) { - struct scatterlist *s; - unsigned int i; + int err; bo->pages = drm_gem_get_pages(&bo->gem); if (IS_ERR(bo->pages)) @@ -223,27 +224,26 @@ static int tegra_bo_get_pages(struct drm_device *drm, struct tegra_bo *bo) bo->num_pages = bo->gem.size >> PAGE_SHIFT; bo->sgt = drm_prime_pages_to_sg(bo->pages, bo->num_pages); - if (IS_ERR(bo->sgt)) + if (IS_ERR(bo->sgt)) { + err = PTR_ERR(bo->sgt); goto put_pages; + } - /* - * Fake up the SG table so that dma_sync_sg_for_device() can be used - * to flush the pages associated with it. - * - * TODO: Replace this by drm_clflash_sg() once it can be implemented - * without relying on symbols that are not exported. - */ - for_each_sg(bo->sgt->sgl, s, bo->sgt->nents, i) - sg_dma_address(s) = sg_phys(s); - - dma_sync_sg_for_device(drm->dev, bo->sgt->sgl, bo->sgt->nents, - DMA_TO_DEVICE); + err = dma_map_sg(drm->dev, bo->sgt->sgl, bo->sgt->nents, + DMA_BIDIRECTIONAL); + if (err == 0) { + err = -EFAULT; + goto free_sgt; + } return 0; +free_sgt: + sg_free_table(bo->sgt); + kfree(bo->sgt); put_pages: drm_gem_put_pages(&bo->gem, bo->pages, false, false); - return PTR_ERR(bo->sgt); + return err; } static int tegra_bo_alloc(struct drm_device *drm, struct tegra_bo *bo) -- cgit From 27e92f1f1600c214bf649daddb9b88b68330a8d1 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 13 Dec 2017 12:25:14 +0100 Subject: drm/tegra: prime: Implement ->{begin,end}_cpu_access() These callbacks allow the exporter to swap in and pin the backing storage for buffers as well as invalidate the cache in preparation for accessing the buffer from the CPU, and flush the cache and unpin the backing storage when the CPU is done modifying the buffer. Signed-off-by: Thierry Reding --- drivers/gpu/drm/tegra/gem.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'drivers/gpu/drm/tegra/gem.c') diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c index 8fc5860ab19a..8b0b4ff64bb4 100644 --- a/drivers/gpu/drm/tegra/gem.c +++ b/drivers/gpu/drm/tegra/gem.c @@ -568,6 +568,34 @@ static void tegra_gem_prime_release(struct dma_buf *buf) drm_gem_dmabuf_release(buf); } +static int tegra_gem_prime_begin_cpu_access(struct dma_buf *buf, + enum dma_data_direction direction) +{ + struct drm_gem_object *gem = buf->priv; + struct tegra_bo *bo = to_tegra_bo(gem); + struct drm_device *drm = gem->dev; + + if (bo->pages) + dma_sync_sg_for_cpu(drm->dev, bo->sgt->sgl, bo->sgt->nents, + DMA_FROM_DEVICE); + + return 0; +} + +static int tegra_gem_prime_end_cpu_access(struct dma_buf *buf, + enum dma_data_direction direction) +{ + struct drm_gem_object *gem = buf->priv; + struct tegra_bo *bo = to_tegra_bo(gem); + struct drm_device *drm = gem->dev; + + if (bo->pages) + dma_sync_sg_for_device(drm->dev, bo->sgt->sgl, bo->sgt->nents, + DMA_TO_DEVICE); + + return 0; +} + static void *tegra_gem_prime_kmap_atomic(struct dma_buf *buf, unsigned long page) { @@ -618,6 +646,8 @@ static const struct dma_buf_ops tegra_gem_prime_dmabuf_ops = { .map_dma_buf = tegra_gem_prime_map_dma_buf, .unmap_dma_buf = tegra_gem_prime_unmap_dma_buf, .release = tegra_gem_prime_release, + .begin_cpu_access = tegra_gem_prime_begin_cpu_access, + .end_cpu_access = tegra_gem_prime_end_cpu_access, .map_atomic = tegra_gem_prime_kmap_atomic, .unmap_atomic = tegra_gem_prime_kunmap_atomic, .map = tegra_gem_prime_kmap, -- cgit