drm/etnaviv: fix mmap operations for userptr and dma-buf objects
authorLucas Stach <l.stach@pengutronix.de>
Wed, 27 Apr 2016 10:27:02 +0000 (12:27 +0200)
committerLucas Stach <l.stach@pengutronix.de>
Fri, 6 May 2016 08:42:33 +0000 (10:42 +0200)
Add an indirect object operations call to allow distinct implementations
of the mmap operation based on the type of the object.

This ensures that the exporter is called to set up the mmap for imported
dma-bufs and disallows mapping of userptr objects through the DRM file,
as this might lead to serious corruption of kernel internal state.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
drivers/gpu/drm/etnaviv/etnaviv_gem.c
drivers/gpu/drm/etnaviv/etnaviv_gem.h
drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c

index 4d2277f6de0366157295f2b0fe6259f4151611ce..df9bcbab922f359bd1837f5b3a5fde457e827457 100644 (file)
@@ -172,7 +172,7 @@ int etnaviv_gem_mmap(struct file *filp, struct vm_area_struct *vma)
        }
 
        obj = to_etnaviv_bo(vma->vm_private_data);
-       return etnaviv_gem_mmap_obj(obj, vma);
+       return obj->ops->mmap(obj, vma);
 }
 
 int etnaviv_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
@@ -544,6 +544,7 @@ static const struct etnaviv_gem_ops etnaviv_gem_shmem_ops = {
        .get_pages = etnaviv_gem_shmem_get_pages,
        .release = etnaviv_gem_shmem_release,
        .vmap = etnaviv_gem_vmap_impl,
+       .mmap = etnaviv_gem_mmap_obj,
 };
 
 void etnaviv_gem_free_object(struct drm_gem_object *obj)
@@ -885,10 +886,17 @@ static void etnaviv_gem_userptr_release(struct etnaviv_gem_object *etnaviv_obj)
        put_task_struct(etnaviv_obj->userptr.task);
 }
 
+static int etnaviv_gem_userptr_mmap_obj(struct etnaviv_gem_object *etnaviv_obj,
+               struct vm_area_struct *vma)
+{
+       return -EINVAL;
+}
+
 static const struct etnaviv_gem_ops etnaviv_gem_userptr_ops = {
        .get_pages = etnaviv_gem_userptr_get_pages,
        .release = etnaviv_gem_userptr_release,
        .vmap = etnaviv_gem_vmap_impl,
+       .mmap = etnaviv_gem_userptr_mmap_obj,
 };
 
 int etnaviv_gem_new_userptr(struct drm_device *dev, struct drm_file *file,
index 02665d8c10eea6a032c1aa4e38bd3e3e71334ccb..e63ff116a3b3df15e15897068d37e0f366803978 100644 (file)
@@ -79,6 +79,7 @@ struct etnaviv_gem_ops {
        int (*get_pages)(struct etnaviv_gem_object *);
        void (*release)(struct etnaviv_gem_object *);
        void *(*vmap)(struct etnaviv_gem_object *);
+       int (*mmap)(struct etnaviv_gem_object *, struct vm_area_struct *);
 };
 
 static inline bool is_active(struct etnaviv_gem_object *etnaviv_obj)
index 4e67395f5fa1c1572aa7051a86538aa16389f807..b93618c1aa69e6c77609d1bc0ce18f308cab7b3f 100644 (file)
@@ -84,10 +84,17 @@ static void *etnaviv_gem_prime_vmap_impl(struct etnaviv_gem_object *etnaviv_obj)
        return dma_buf_vmap(etnaviv_obj->base.import_attach->dmabuf);
 }
 
+static int etnaviv_gem_prime_mmap_obj(struct etnaviv_gem_object *etnaviv_obj,
+               struct vm_area_struct *vma)
+{
+       return dma_buf_mmap(etnaviv_obj->base.dma_buf, vma, 0);
+}
+
 static const struct etnaviv_gem_ops etnaviv_gem_prime_ops = {
        /* .get_pages should never be called */
        .release = etnaviv_gem_prime_release,
        .vmap = etnaviv_gem_prime_vmap_impl,
+       .mmap = etnaviv_gem_prime_mmap_obj,
 };
 
 struct drm_gem_object *etnaviv_gem_prime_import_sg_table(struct drm_device *dev,