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

drm/exynos: use drm generic mmap interface

This patch removes DRM_EXYNOS_GEM_MMAP ictrl feature specific
to Exynos drm and instead uses drm generic mmap.

We had used the interface specific to Exynos drm to do mmap directly,
not to use demand paging which maps each page with physical memory
at page fault handler. We don't need the specific mmap interface
because the drm generic mmap which uses vm offset manager stuff can
also do mmap directly.

This patch makes a userspace region to be mapped with whole physical
memory region allocated by userspace request when mmap system call is
requested.

Changelog v2:
- do not set VM_IO, VM_DONTEXPEND and VM_DONTDUMP. These flags were already
set by drm_gem_mmap
- do not include <linux/anon_inodes.h>, which isn't needed anymore.

Signed-off-by: Inki Dae <inki.dae@samsung.com>

authored by

Inki Dae and committed by
Inki Dae
832316c7 d931589c

+16 -132
-26
drivers/gpu/drm/exynos/exynos_drm_drv.c
··· 15 15 #include <drm/drmP.h> 16 16 #include <drm/drm_crtc_helper.h> 17 17 18 - #include <linux/anon_inodes.h> 19 18 #include <linux/component.h> 20 19 21 20 #include <drm/exynos_drm.h> ··· 165 166 return 0; 166 167 } 167 168 168 - static const struct file_operations exynos_drm_gem_fops = { 169 - .mmap = exynos_drm_gem_mmap_buffer, 170 - }; 171 - 172 169 static int exynos_drm_suspend(struct drm_device *dev, pm_message_t state) 173 170 { 174 171 struct drm_connector *connector; ··· 203 208 static int exynos_drm_open(struct drm_device *dev, struct drm_file *file) 204 209 { 205 210 struct drm_exynos_file_private *file_priv; 206 - struct file *anon_filp; 207 211 int ret; 208 212 209 213 file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL); ··· 215 221 if (ret) 216 222 goto err_file_priv_free; 217 223 218 - anon_filp = anon_inode_getfile("exynos_gem", &exynos_drm_gem_fops, 219 - NULL, 0); 220 - if (IS_ERR(anon_filp)) { 221 - ret = PTR_ERR(anon_filp); 222 - goto err_subdrv_close; 223 - } 224 - 225 - anon_filp->f_mode = FMODE_READ | FMODE_WRITE; 226 - file_priv->anon_filp = anon_filp; 227 - 228 224 return ret; 229 - 230 - err_subdrv_close: 231 - exynos_drm_subdrv_close(dev, file); 232 225 233 226 err_file_priv_free: 234 227 kfree(file_priv); ··· 232 251 static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file) 233 252 { 234 253 struct exynos_drm_private *private = dev->dev_private; 235 - struct drm_exynos_file_private *file_priv; 236 254 struct drm_pending_vblank_event *v, *vt; 237 255 struct drm_pending_event *e, *et; 238 256 unsigned long flags; ··· 257 277 } 258 278 spin_unlock_irqrestore(&dev->event_lock, flags); 259 279 260 - file_priv = file->driver_priv; 261 - if (file_priv->anon_filp) 262 - fput(file_priv->anon_filp); 263 - 264 280 kfree(file->driver_priv); 265 281 file->driver_priv = NULL; 266 282 } ··· 275 299 static const struct drm_ioctl_desc exynos_ioctls[] = { 276 300 DRM_IOCTL_DEF_DRV(EXYNOS_GEM_CREATE, exynos_drm_gem_create_ioctl, 277 301 DRM_UNLOCKED | DRM_AUTH), 278 - DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MMAP, 279 - exynos_drm_gem_mmap_ioctl, DRM_UNLOCKED | DRM_AUTH), 280 302 DRM_IOCTL_DEF_DRV(EXYNOS_GEM_GET, 281 303 exynos_drm_gem_get_ioctl, DRM_UNLOCKED), 282 304 DRM_IOCTL_DEF_DRV(EXYNOS_VIDI_CONNECTION,
-1
drivers/gpu/drm/exynos/exynos_drm_drv.h
··· 240 240 struct drm_exynos_file_private { 241 241 struct exynos_drm_g2d_private *g2d_priv; 242 242 struct device *ipp_dev; 243 - struct file *anon_filp; 244 243 }; 245 244 246 245 /*
+16 -73
drivers/gpu/drm/exynos/exynos_drm_gem.c
··· 318 318 drm_gem_object_unreference_unlocked(obj); 319 319 } 320 320 321 - int exynos_drm_gem_mmap_buffer(struct file *filp, 321 + int exynos_drm_gem_mmap_buffer(struct exynos_drm_gem_obj *exynos_gem_obj, 322 322 struct vm_area_struct *vma) 323 323 { 324 - struct drm_gem_object *obj = filp->private_data; 325 - struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj); 326 - struct drm_device *drm_dev = obj->dev; 324 + struct drm_device *drm_dev = exynos_gem_obj->base.dev; 327 325 struct exynos_drm_gem_buf *buffer; 328 326 unsigned long vm_size; 329 327 int ret; 330 328 331 - WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex)); 332 - 333 - vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP; 334 - vma->vm_private_data = obj; 335 - vma->vm_ops = drm_dev->driver->gem_vm_ops; 336 - 337 - update_vm_cache_attr(exynos_gem_obj, vma); 329 + vma->vm_flags &= ~VM_PFNMAP; 330 + vma->vm_pgoff = 0; 338 331 339 332 vm_size = vma->vm_end - vma->vm_start; 340 333 ··· 348 355 DRM_ERROR("failed to mmap.\n"); 349 356 return ret; 350 357 } 351 - 352 - /* 353 - * take a reference to this mapping of the object. And this reference 354 - * is unreferenced by the corresponding vm_close call. 355 - */ 356 - drm_gem_object_reference(obj); 357 - 358 - drm_vm_open_locked(drm_dev, vma); 359 - 360 - return 0; 361 - } 362 - 363 - int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data, 364 - struct drm_file *file_priv) 365 - { 366 - struct drm_exynos_file_private *exynos_file_priv; 367 - struct drm_exynos_gem_mmap *args = data; 368 - struct drm_gem_object *obj; 369 - struct file *anon_filp; 370 - unsigned long addr; 371 - 372 - if (!(dev->driver->driver_features & DRIVER_GEM)) { 373 - DRM_ERROR("does not support GEM.\n"); 374 - return -ENODEV; 375 - } 376 - 377 - mutex_lock(&dev->struct_mutex); 378 - 379 - obj = drm_gem_object_lookup(dev, file_priv, args->handle); 380 - if (!obj) { 381 - DRM_ERROR("failed to lookup gem object.\n"); 382 - mutex_unlock(&dev->struct_mutex); 383 - return -EINVAL; 384 - } 385 - 386 - exynos_file_priv = file_priv->driver_priv; 387 - anon_filp = exynos_file_priv->anon_filp; 388 - anon_filp->private_data = obj; 389 - 390 - addr = vm_mmap(anon_filp, 0, args->size, PROT_READ | PROT_WRITE, 391 - MAP_SHARED, 0); 392 - 393 - drm_gem_object_unreference(obj); 394 - 395 - if (IS_ERR_VALUE(addr)) { 396 - mutex_unlock(&dev->struct_mutex); 397 - return (int)addr; 398 - } 399 - 400 - mutex_unlock(&dev->struct_mutex); 401 - 402 - args->mapped = addr; 403 - 404 - DRM_DEBUG_KMS("mapped = 0x%lx\n", (unsigned long)args->mapped); 405 358 406 359 return 0; 407 360 } ··· 632 693 exynos_gem_obj = to_exynos_gem_obj(obj); 633 694 634 695 ret = check_gem_flags(exynos_gem_obj->flags); 635 - if (ret) { 636 - drm_gem_vm_close(vma); 637 - drm_gem_free_mmap_offset(obj); 638 - return ret; 639 - } 640 - 641 - vma->vm_flags &= ~VM_PFNMAP; 642 - vma->vm_flags |= VM_MIXEDMAP; 696 + if (ret) 697 + goto err_close_vm; 643 698 644 699 update_vm_cache_attr(exynos_gem_obj, vma); 700 + 701 + ret = exynos_drm_gem_mmap_buffer(exynos_gem_obj, vma); 702 + if (ret) 703 + goto err_close_vm; 704 + 705 + return ret; 706 + 707 + err_close_vm: 708 + drm_gem_vm_close(vma); 709 + drm_gem_free_mmap_offset(obj); 645 710 646 711 return ret; 647 712 }
-10
drivers/gpu/drm/exynos/exynos_drm_gem.h
··· 111 111 unsigned int gem_handle, 112 112 struct drm_file *filp); 113 113 114 - /* 115 - * mmap the physically continuous memory that a gem object contains 116 - * to user space. 117 - */ 118 - int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data, 119 - struct drm_file *file_priv); 120 - 121 - int exynos_drm_gem_mmap_buffer(struct file *filp, 122 - struct vm_area_struct *vma); 123 - 124 114 /* map user space allocated by malloc to pages. */ 125 115 int exynos_drm_gem_userptr_ioctl(struct drm_device *dev, void *data, 126 116 struct drm_file *file_priv);
-22
include/uapi/drm/exynos_drm.h
··· 33 33 }; 34 34 35 35 /** 36 - * A structure for mapping buffer. 37 - * 38 - * @handle: a handle to gem object created. 39 - * @pad: just padding to be 64-bit aligned. 40 - * @size: memory size to be mapped. 41 - * @mapped: having user virtual address mmaped. 42 - * - this variable would be filled by exynos gem module 43 - * of kernel side with user virtual address which is allocated 44 - * by do_mmap(). 45 - */ 46 - struct drm_exynos_gem_mmap { 47 - unsigned int handle; 48 - unsigned int pad; 49 - uint64_t size; 50 - uint64_t mapped; 51 - }; 52 - 53 - /** 54 36 * A structure to gem information. 55 37 * 56 38 * @handle: a handle to gem object created. ··· 284 302 }; 285 303 286 304 #define DRM_EXYNOS_GEM_CREATE 0x00 287 - #define DRM_EXYNOS_GEM_MMAP 0x02 288 305 /* Reserved 0x03 ~ 0x05 for exynos specific gem ioctl */ 289 306 #define DRM_EXYNOS_GEM_GET 0x04 290 307 #define DRM_EXYNOS_VIDI_CONNECTION 0x07 ··· 301 320 302 321 #define DRM_IOCTL_EXYNOS_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + \ 303 322 DRM_EXYNOS_GEM_CREATE, struct drm_exynos_gem_create) 304 - 305 - #define DRM_IOCTL_EXYNOS_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + \ 306 - DRM_EXYNOS_GEM_MMAP, struct drm_exynos_gem_mmap) 307 323 308 324 #define DRM_IOCTL_EXYNOS_GEM_GET DRM_IOWR(DRM_COMMAND_BASE + \ 309 325 DRM_EXYNOS_GEM_GET, struct drm_exynos_gem_info)