Commit 41315b79 authored by Daniel Kurtz's avatar Daniel Kurtz Committed by Daniel Vetter

drm/rockchip: use drm_gem_mmap helpers

Rather than (incompletely [0]) re-implementing drm_gem_mmap() and
drm_gem_mmap_obj() helpers, call them directly from the rockchip mmap
routines.

Once the core functions return successfully, the rockchip mmap routines
can still use dma_mmap_attrs() to simply mmap the entire buffer.

[0] Previously, we were performing the mmap() without first taking a
reference on the underlying gem buffer.  This could leak ptes if the gem
object is destroyed while userspace is still holding the mapping.
Signed-off-by: default avatarDaniel Kurtz <djkurtz@chromium.org>
Reviewed-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Cc: stable@vger.kernel.org
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent e24ff467
...@@ -54,55 +54,56 @@ static void rockchip_gem_free_buf(struct rockchip_gem_object *rk_obj) ...@@ -54,55 +54,56 @@ static void rockchip_gem_free_buf(struct rockchip_gem_object *rk_obj)
&rk_obj->dma_attrs); &rk_obj->dma_attrs);
} }
int rockchip_gem_mmap_buf(struct drm_gem_object *obj, static int rockchip_drm_gem_object_mmap(struct drm_gem_object *obj,
struct vm_area_struct *vma) struct vm_area_struct *vma)
{ {
int ret;
struct rockchip_gem_object *rk_obj = to_rockchip_obj(obj); struct rockchip_gem_object *rk_obj = to_rockchip_obj(obj);
struct drm_device *drm = obj->dev; struct drm_device *drm = obj->dev;
unsigned long vm_size;
vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP; /*
vm_size = vma->vm_end - vma->vm_start; * dma_alloc_attrs() allocated a struct page table for rk_obj, so clear
* VM_PFNMAP flag that was set by drm_gem_mmap_obj()/drm_gem_mmap().
if (vm_size > obj->size) */
return -EINVAL; vma->vm_flags &= ~VM_PFNMAP;
return dma_mmap_attrs(drm->dev, vma, rk_obj->kvaddr, rk_obj->dma_addr, ret = dma_mmap_attrs(drm->dev, vma, rk_obj->kvaddr, rk_obj->dma_addr,
obj->size, &rk_obj->dma_attrs); obj->size, &rk_obj->dma_attrs);
if (ret)
drm_gem_vm_close(vma);
return ret;
} }
/* drm driver mmap file operations */ int rockchip_gem_mmap_buf(struct drm_gem_object *obj,
int rockchip_gem_mmap(struct file *filp, struct vm_area_struct *vma) struct vm_area_struct *vma)
{ {
struct drm_file *priv = filp->private_data; struct drm_device *drm = obj->dev;
struct drm_device *dev = priv->minor->dev;
struct drm_gem_object *obj;
struct drm_vma_offset_node *node;
int ret; int ret;
if (drm_device_is_unplugged(dev)) mutex_lock(&drm->struct_mutex);
return -ENODEV; ret = drm_gem_mmap_obj(obj, obj->size, vma);
mutex_unlock(&drm->struct_mutex);
if (ret)
return ret;
mutex_lock(&dev->struct_mutex); return rockchip_drm_gem_object_mmap(obj, vma);
}
node = drm_vma_offset_exact_lookup(dev->vma_offset_manager, /* drm driver mmap file operations */
vma->vm_pgoff, int rockchip_gem_mmap(struct file *filp, struct vm_area_struct *vma)
vma_pages(vma)); {
if (!node) { struct drm_gem_object *obj;
mutex_unlock(&dev->struct_mutex); int ret;
DRM_ERROR("failed to find vma node.\n");
return -EINVAL;
} else if (!drm_vma_node_is_allowed(node, filp)) {
mutex_unlock(&dev->struct_mutex);
return -EACCES;
}
obj = container_of(node, struct drm_gem_object, vma_node); ret = drm_gem_mmap(filp, vma);
ret = rockchip_gem_mmap_buf(obj, vma); if (ret)
return ret;
mutex_unlock(&dev->struct_mutex); obj = vma->vm_private_data;
return ret; return rockchip_drm_gem_object_mmap(obj, vma);
} }
struct rockchip_gem_object * struct rockchip_gem_object *
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment