Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/20191016115203.20095-2-kraxel@redhat.com

+41 -9
+18 -9
drivers/gpu/drm/drm_gem.c
··· 1099 1099 struct vm_area_struct *vma) 1100 1100 { 1101 1101 struct drm_device *dev = obj->dev; 1102 + int ret; 1102 1103 1103 1104 /* Check for valid size. */ 1104 1105 if (obj_size < vma->vm_end - vma->vm_start) 1105 1106 return -EINVAL; 1106 1107 1107 - if (obj->funcs && obj->funcs->vm_ops) 1108 - vma->vm_ops = obj->funcs->vm_ops; 1109 - else if (dev->driver->gem_vm_ops) 1110 - vma->vm_ops = dev->driver->gem_vm_ops; 1111 - else 1112 - return -EINVAL; 1108 + if (obj->funcs && obj->funcs->mmap) { 1109 + ret = obj->funcs->mmap(obj, vma); 1110 + if (ret) 1111 + return ret; 1112 + WARN_ON(!(vma->vm_flags & VM_DONTEXPAND)); 1113 + } else { 1114 + if (obj->funcs && obj->funcs->vm_ops) 1115 + vma->vm_ops = obj->funcs->vm_ops; 1116 + else if (dev->driver->gem_vm_ops) 1117 + vma->vm_ops = dev->driver->gem_vm_ops; 1118 + else 1119 + return -EINVAL; 1113 1120 1114 - vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP; 1121 + vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP; 1122 + vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags)); 1123 + vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); 1124 + } 1125 + 1115 1126 vma->vm_private_data = obj; 1116 - vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags)); 1117 - vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); 1118 1127 1119 1128 /* Take a ref for this mapping of the object, so that the fault 1120 1129 * handler can dereference the mmap offset's pointer to the object.
+9
drivers/gpu/drm/drm_prime.c
··· 713 713 struct file *fil; 714 714 int ret; 715 715 716 + if (obj->funcs && obj->funcs->mmap) { 717 + ret = obj->funcs->mmap(obj, vma); 718 + if (ret) 719 + return ret; 720 + vma->vm_private_data = obj; 721 + drm_gem_object_get(obj); 722 + return 0; 723 + } 724 + 716 725 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 717 726 fil = kzalloc(sizeof(*fil), GFP_KERNEL); 718 727 if (!priv || !fil) {
+14
include/drm/drm_gem.h
··· 151 151 void (*vunmap)(struct drm_gem_object *obj, void *vaddr); 152 152 153 153 /** 154 + * @mmap: 155 + * 156 + * Handle mmap() of the gem object, setup vma accordingly. 157 + * 158 + * This callback is optional. 159 + * 160 + * The callback is used by by both drm_gem_mmap_obj() and 161 + * drm_gem_prime_mmap(). When @mmap is present @vm_ops is not 162 + * used, the @mmap callback must set vma->vm_ops instead. 163 + * 164 + */ 165 + int (*mmap)(struct drm_gem_object *obj, struct vm_area_struct *vma); 166 + 167 + /** 154 168 * @vm_ops: 155 169 * 156 170 * Virtual memory operations used with mmap.