From 6f3ffc19157a14b182d9d0c449cd613cef421fe1 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Tue, 12 Jan 2016 18:17:19 +0100 Subject: [PATCH 1/4] timer: add setup_deferrable_timer macro Add the trivial missing macro to setup a deferrable timer. Signed-off-by: Lucas Stach Acked-by: Thomas Gleixner --- include/linux/timer.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/timer.h b/include/linux/timer.h index 61aa61dc410c..20ac746f3eb3 100644 --- a/include/linux/timer.h +++ b/include/linux/timer.h @@ -145,6 +145,8 @@ static inline void init_timer_on_stack_key(struct timer_list *timer, #define setup_timer(timer, fn, data) \ __setup_timer((timer), (fn), (data), 0) +#define setup_deferrable_timer(timer, fn, data) \ + __setup_timer((timer), (fn), (data), TIMER_DEFERRABLE) #define setup_timer_on_stack(timer, fn, data) \ __setup_timer_on_stack((timer), (fn), (data), 0) #define setup_deferrable_timer_on_stack(timer, fn, data) \ From 946dd8d5ec680c0831ed27a9bab8afa424f2c5a8 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Wed, 23 Mar 2016 18:24:45 +0100 Subject: [PATCH 2/4] drm/etnaviv: use deferrable timer for hangcheck handler The hangcheck handler is already running with very coarse timeouts, so it doesn't hurt to combine this timer with other wakeups in the system. Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c index 306dde18a94a..049d00d8ded5 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c @@ -1528,8 +1528,8 @@ static int etnaviv_gpu_bind(struct device *dev, struct device *master, INIT_WORK(&gpu->recover_work, recover_worker); init_waitqueue_head(&gpu->fence_event); - setup_timer(&gpu->hangcheck_timer, hangcheck_handler, - (unsigned long)gpu); + setup_deferrable_timer(&gpu->hangcheck_timer, hangcheck_handler, + (unsigned long)gpu); priv->gpu[priv->num_gpus++] = gpu; From 0e7f26e6b950fe586c8aa6ff6f87b9936ae32ebb Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Wed, 27 Apr 2016 12:12:00 +0200 Subject: [PATCH 3/4] drm/etnaviv: take etnaviv_gem_obj in etnaviv_gem_mmap_obj This function will be changed to be called indirectly and this prototype change brings it in line with all the other indirect object calls. Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_gem.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c index 281c6eca20a8..4d2277f6de03 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c @@ -129,10 +129,9 @@ void etnaviv_gem_put_pages(struct etnaviv_gem_object *etnaviv_obj) /* when we start tracking the pin count, then do something here */ } -static int etnaviv_gem_mmap_obj(struct drm_gem_object *obj, +static int etnaviv_gem_mmap_obj(struct etnaviv_gem_object *etnaviv_obj, struct vm_area_struct *vma) { - struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj); pgprot_t vm_page_prot; vma->vm_flags &= ~VM_PFNMAP; @@ -151,9 +150,9 @@ static int etnaviv_gem_mmap_obj(struct drm_gem_object *obj, * in particular in the case of mmap'd dmabufs) */ fput(vma->vm_file); - get_file(obj->filp); + get_file(etnaviv_obj->base.filp); vma->vm_pgoff = 0; - vma->vm_file = obj->filp; + vma->vm_file = etnaviv_obj->base.filp; vma->vm_page_prot = vm_page_prot; } @@ -173,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(vma->vm_private_data, vma); + return etnaviv_gem_mmap_obj(obj, vma); } int etnaviv_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) From a10e2bde5d9173570d97a4d7cdf038232baaf47e Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Wed, 27 Apr 2016 12:27:02 +0200 Subject: [PATCH 4/4] drm/etnaviv: fix mmap operations for userptr and dma-buf objects 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 --- drivers/gpu/drm/etnaviv/etnaviv_gem.c | 10 +++++++++- drivers/gpu/drm/etnaviv/etnaviv_gem.h | 1 + drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c | 7 +++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c index 4d2277f6de03..df9bcbab922f 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c @@ -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, diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.h b/drivers/gpu/drm/etnaviv/etnaviv_gem.h index 02665d8c10ee..e63ff116a3b3 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.h @@ -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) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c index 4e67395f5fa1..b93618c1aa69 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c @@ -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,