drm/tegra: gem: Implement mmap() for PRIME buffers
authorThierry Reding <treding@nvidia.com>
Tue, 15 Aug 2017 13:42:40 +0000 (15:42 +0200)
committerThierry Reding <treding@nvidia.com>
Thu, 17 Aug 2017 15:57:18 +0000 (17:57 +0200)
The mapping of PRIME buffers can reuse much of the GEM mapping code, so
extract the common bits into a new tegra_gem_mmap() helper.

Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Thierry Reding <treding@nvidia.com>
drivers/gpu/drm/tegra/gem.c

index fe77bcd23800e20e44830b24aeeb91cc21077fe1..ef068556a9d7ea6752f51d4e5e0624fe4e6d1afd 100644 (file)
@@ -481,30 +481,28 @@ const struct vm_operations_struct tegra_bo_vm_ops = {
        .close = drm_gem_vm_close,
 };
 
-int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma)
+static int tegra_gem_mmap(struct drm_gem_object *gem,
+                         struct vm_area_struct *vma)
 {
-       struct drm_gem_object *gem;
-       struct tegra_bo *bo;
-       int ret;
-
-       ret = drm_gem_mmap(file, vma);
-       if (ret)
-               return ret;
-
-       gem = vma->vm_private_data;
-       bo = to_tegra_bo(gem);
+       struct tegra_bo *bo = to_tegra_bo(gem);
 
        if (!bo->pages) {
                unsigned long vm_pgoff = vma->vm_pgoff;
+               int err;
 
+               /*
+                * Clear the VM_PFNMAP flag that was set by drm_gem_mmap(),
+                * and set the vm_pgoff (used as a fake buffer offset by DRM)
+                * to 0 as we want to map the whole buffer.
+                */
                vma->vm_flags &= ~VM_PFNMAP;
                vma->vm_pgoff = 0;
 
-               ret = dma_mmap_wc(gem->dev->dev, vma, bo->vaddr, bo->paddr,
+               err = dma_mmap_wc(gem->dev->dev, vma, bo->vaddr, bo->paddr,
                                  gem->size);
-               if (ret) {
+               if (err < 0) {
                        drm_gem_vm_close(vma);
-                       return ret;
+                       return err;
                }
 
                vma->vm_pgoff = vm_pgoff;
@@ -520,6 +518,20 @@ int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma)
        return 0;
 }
 
+int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct drm_gem_object *gem;
+       int err;
+
+       err = drm_gem_mmap(file, vma);
+       if (err < 0)
+               return err;
+
+       gem = vma->vm_private_data;
+
+       return tegra_gem_mmap(gem, vma);
+}
+
 static struct sg_table *
 tegra_gem_prime_map_dma_buf(struct dma_buf_attachment *attach,
                            enum dma_data_direction dir)
@@ -603,7 +615,14 @@ static void tegra_gem_prime_kunmap(struct dma_buf *buf, unsigned long page,
 
 static int tegra_gem_prime_mmap(struct dma_buf *buf, struct vm_area_struct *vma)
 {
-       return -EINVAL;
+       struct drm_gem_object *gem = buf->priv;
+       int err;
+
+       err = drm_gem_mmap_obj(gem, gem->size, vma);
+       if (err < 0)
+               return err;
+
+       return tegra_gem_mmap(gem, vma);
 }
 
 static void *tegra_gem_prime_vmap(struct dma_buf *buf)