Commit c40069cb authored by Gerd Hoffmann's avatar Gerd Hoffmann
Browse files

drm: add mmap() to drm_gem_object_funcs



drm_gem_object_funcs->vm_ops alone can't handle everything which needs
to be done for mmap(), tweaking vm_flags for example.  So add a new
mmap() callback to drm_gem_object_funcs where this code can go to.

Note that the vm_ops field is not used in case the mmap callback is
present, it is expected that the callback sets vma->vm_ops instead.

Also setting vm_flags and vm_page_prot is the job of the new callback.
so drivers have more control over these flags.

drm_gem_mmap_obj() will use the new callback for object specific mmap
setup.  With this in place the need for driver-speific fops->mmap
callbacks goes away, drm_gem_mmap can be hooked instead.

drm_gem_prime_mmap() will use the new callback too to just mmap gem
objects directly instead of jumping though loops to make
drm_gem_object_lookup() and fops->mmap work.

Signed-off-by: default avatarGerd Hoffmann <kraxel@redhat.com>
Reviewed-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/20191016115203.20095-2-kraxel@redhat.com
parent 3c2ed9ce
Loading
Loading
Loading
Loading
+18 −9
Original line number Diff line number Diff line
@@ -1099,11 +1099,18 @@ int drm_gem_mmap_obj(struct drm_gem_object *obj, unsigned long obj_size,
		     struct vm_area_struct *vma)
{
	struct drm_device *dev = obj->dev;
	int ret;

	/* Check for valid size. */
	if (obj_size < vma->vm_end - vma->vm_start)
		return -EINVAL;

	if (obj->funcs && obj->funcs->mmap) {
		ret = obj->funcs->mmap(obj, vma);
		if (ret)
			return ret;
		WARN_ON(!(vma->vm_flags & VM_DONTEXPAND));
	} else {
		if (obj->funcs && obj->funcs->vm_ops)
			vma->vm_ops = obj->funcs->vm_ops;
		else if (dev->driver->gem_vm_ops)
@@ -1112,9 +1119,11 @@ int drm_gem_mmap_obj(struct drm_gem_object *obj, unsigned long obj_size,
			return -EINVAL;

		vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP;
	vma->vm_private_data = obj;
		vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
		vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot);
	}

	vma->vm_private_data = obj;

	/* Take a ref for this mapping of the object, so that the fault
	 * handler can dereference the mmap offset's pointer to the object.
+9 −0
Original line number Diff line number Diff line
@@ -713,6 +713,15 @@ int drm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
	struct file *fil;
	int ret;

	if (obj->funcs && obj->funcs->mmap) {
		ret = obj->funcs->mmap(obj, vma);
		if (ret)
			return ret;
		vma->vm_private_data = obj;
		drm_gem_object_get(obj);
		return 0;
	}

	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
	fil = kzalloc(sizeof(*fil), GFP_KERNEL);
	if (!priv || !fil) {
+14 −0
Original line number Diff line number Diff line
@@ -150,6 +150,20 @@ struct drm_gem_object_funcs {
	 */
	void (*vunmap)(struct drm_gem_object *obj, void *vaddr);

	/**
	 * @mmap:
	 *
	 * Handle mmap() of the gem object, setup vma accordingly.
	 *
	 * This callback is optional.
	 *
	 * The callback is used by by both drm_gem_mmap_obj() and
	 * drm_gem_prime_mmap().  When @mmap is present @vm_ops is not
	 * used, the @mmap callback must set vma->vm_ops instead.
	 *
	 */
	int (*mmap)(struct drm_gem_object *obj, struct vm_area_struct *vma);

	/**
	 * @vm_ops:
	 *