2 * Copyright (C) ROCKCHIP, Inc.
3 * Author:yzq<yzq@rock-chips.com>
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
15 #include <linux/shmem_fs.h>
16 #include <drm/rockchip_drm.h>
18 #include "rockchip_drm_drv.h"
19 #include "rockchip_drm_gem.h"
20 #include "rockchip_drm_buf.h"
22 static unsigned int convert_to_vm_err_msg(int msg)
30 out_msg = VM_FAULT_NOPAGE;
34 out_msg = VM_FAULT_OOM;
38 out_msg = VM_FAULT_SIGBUS;
45 static int check_gem_flags(unsigned int flags)
47 if (flags & ~(ROCKCHIP_BO_MASK)) {
48 DRM_ERROR("invalid flags.\n");
55 static void update_vm_cache_attr(struct rockchip_drm_gem_obj *obj,
56 struct vm_area_struct *vma)
58 DRM_DEBUG_KMS("flags = 0x%x\n", obj->flags);
60 /* non-cachable as default. */
61 if (obj->flags & ROCKCHIP_BO_CACHABLE)
62 vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
63 else if (obj->flags & ROCKCHIP_BO_WC)
65 pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
68 pgprot_noncached(vm_get_page_prot(vma->vm_flags));
71 static unsigned long roundup_gem_size(unsigned long size, unsigned int flags)
75 return roundup(size, PAGE_SIZE);
78 static int rockchip_drm_gem_map_buf(struct drm_gem_object *obj,
79 struct vm_area_struct *vma,
80 unsigned long f_vaddr,
83 struct rockchip_drm_gem_obj *rockchip_gem_obj = to_rockchip_gem_obj(obj);
84 struct rockchip_drm_gem_buf *buf = rockchip_gem_obj->buffer;
85 struct scatterlist *sgl;
92 if (page_offset >= (buf->size >> PAGE_SHIFT)) {
93 DRM_ERROR("invalid page offset\n");
98 for_each_sg(buf->sgt->sgl, sgl, buf->sgt->nents, i) {
99 if (page_offset < (sgl->length >> PAGE_SHIFT))
101 page_offset -= (sgl->length >> PAGE_SHIFT);
104 pfn = __phys_to_pfn(sg_phys(sgl)) + page_offset;
106 return vm_insert_mixed(vma, f_vaddr, pfn);
109 static int rockchip_drm_gem_handle_create(struct drm_gem_object *obj,
110 struct drm_file *file_priv,
111 unsigned int *handle)
116 * allocate a id of idr table where the obj is registered
117 * and handle has the id what user can see.
119 ret = drm_gem_handle_create(file_priv, obj, handle);
123 DRM_DEBUG_KMS("gem handle = 0x%x\n", *handle);
125 /* drop reference from allocate - handle holds it now. */
126 drm_gem_object_unreference_unlocked(obj);
131 void rockchip_drm_gem_destroy(struct rockchip_drm_gem_obj *rockchip_gem_obj)
133 struct drm_gem_object *obj;
134 struct rockchip_drm_gem_buf *buf;
136 DRM_DEBUG_KMS("%s\n", __FILE__);
138 obj = &rockchip_gem_obj->base;
139 buf = rockchip_gem_obj->buffer;
141 DRM_DEBUG_KMS("handle count = %d\n", atomic_read(&obj->handle_count));
144 * do not release memory region from exporter.
146 * the region will be released by exporter
147 * once dmabuf's refcount becomes 0.
149 if (obj->import_attach)
152 rockchip_drm_free_buf(obj->dev, rockchip_gem_obj->flags, buf);
155 rockchip_drm_fini_buf(obj->dev, buf);
156 rockchip_gem_obj->buffer = NULL;
158 if (obj->map_list.map)
159 drm_gem_free_mmap_offset(obj);
161 /* release file pointer to gem object. */
162 drm_gem_object_release(obj);
164 kfree(rockchip_gem_obj);
165 rockchip_gem_obj = NULL;
168 unsigned long rockchip_drm_gem_get_size(struct drm_device *dev,
169 unsigned int gem_handle,
170 struct drm_file *file_priv)
172 struct rockchip_drm_gem_obj *rockchip_gem_obj;
173 struct drm_gem_object *obj;
175 obj = drm_gem_object_lookup(dev, file_priv, gem_handle);
177 DRM_ERROR("failed to lookup gem object.\n");
181 rockchip_gem_obj = to_rockchip_gem_obj(obj);
183 drm_gem_object_unreference_unlocked(obj);
185 return rockchip_gem_obj->buffer->size;
189 struct rockchip_drm_gem_obj *rockchip_drm_gem_init(struct drm_device *dev,
192 struct rockchip_drm_gem_obj *rockchip_gem_obj;
193 struct drm_gem_object *obj;
196 rockchip_gem_obj = kzalloc(sizeof(*rockchip_gem_obj), GFP_KERNEL);
197 if (!rockchip_gem_obj) {
198 DRM_ERROR("failed to allocate rockchip gem object\n");
202 rockchip_gem_obj->size = size;
203 obj = &rockchip_gem_obj->base;
205 ret = drm_gem_object_init(dev, obj, size);
207 DRM_ERROR("failed to initialize gem object\n");
208 kfree(rockchip_gem_obj);
212 DRM_DEBUG_KMS("created file object = 0x%x\n", (unsigned int)obj->filp);
214 return rockchip_gem_obj;
217 struct rockchip_drm_gem_obj *rockchip_drm_gem_create(struct drm_device *dev,
221 struct rockchip_drm_gem_obj *rockchip_gem_obj;
222 struct rockchip_drm_gem_buf *buf;
226 DRM_ERROR("invalid size.\n");
227 return ERR_PTR(-EINVAL);
230 size = roundup_gem_size(size, flags);
231 DRM_DEBUG_KMS("%s\n", __FILE__);
233 ret = check_gem_flags(flags);
237 buf = rockchip_drm_init_buf(dev, size);
239 return ERR_PTR(-ENOMEM);
241 rockchip_gem_obj = rockchip_drm_gem_init(dev, size);
242 if (!rockchip_gem_obj) {
247 rockchip_gem_obj->buffer = buf;
249 /* set memory type and cache attribute from user side. */
250 rockchip_gem_obj->flags = flags;
252 ret = rockchip_drm_alloc_buf(dev, buf, flags);
254 drm_gem_object_release(&rockchip_gem_obj->base);
258 return rockchip_gem_obj;
261 rockchip_drm_fini_buf(dev, buf);
265 int rockchip_drm_gem_create_ioctl(struct drm_device *dev, void *data,
266 struct drm_file *file_priv)
268 struct drm_rockchip_gem_create *args = data;
269 struct rockchip_drm_gem_obj *rockchip_gem_obj;
272 DRM_DEBUG_KMS("%s\n", __FILE__);
274 rockchip_gem_obj = rockchip_drm_gem_create(dev, args->flags, args->size);
275 if (IS_ERR(rockchip_gem_obj))
276 return PTR_ERR(rockchip_gem_obj);
278 ret = rockchip_drm_gem_handle_create(&rockchip_gem_obj->base, file_priv,
281 rockchip_drm_gem_destroy(rockchip_gem_obj);
288 dma_addr_t *rockchip_drm_gem_get_dma_addr(struct drm_device *dev,
289 unsigned int gem_handle,
290 struct drm_file *filp)
292 struct rockchip_drm_gem_obj *rockchip_gem_obj;
293 struct drm_gem_object *obj;
295 obj = drm_gem_object_lookup(dev, filp, gem_handle);
297 DRM_ERROR("failed to lookup gem object.\n");
298 return ERR_PTR(-EINVAL);
301 rockchip_gem_obj = to_rockchip_gem_obj(obj);
303 return &rockchip_gem_obj->buffer->dma_addr;
306 void rockchip_drm_gem_put_dma_addr(struct drm_device *dev,
307 unsigned int gem_handle,
308 struct drm_file *filp)
310 struct rockchip_drm_gem_obj *rockchip_gem_obj;
311 struct drm_gem_object *obj;
313 obj = drm_gem_object_lookup(dev, filp, gem_handle);
315 DRM_ERROR("failed to lookup gem object.\n");
319 rockchip_gem_obj = to_rockchip_gem_obj(obj);
321 drm_gem_object_unreference_unlocked(obj);
324 * decrease obj->refcount one more time because we has already
325 * increased it at rockchip_drm_gem_get_dma_addr().
327 drm_gem_object_unreference_unlocked(obj);
330 int rockchip_drm_gem_map_offset_ioctl(struct drm_device *dev, void *data,
331 struct drm_file *file_priv)
333 struct drm_rockchip_gem_map_off *args = data;
335 DRM_DEBUG_KMS("%s\n", __FILE__);
337 DRM_DEBUG_KMS("handle = 0x%x, offset = 0x%lx\n",
338 args->handle, (unsigned long)args->offset);
340 if (!(dev->driver->driver_features & DRIVER_GEM)) {
341 DRM_ERROR("does not support GEM.\n");
345 return rockchip_drm_gem_dumb_map_offset(file_priv, dev, args->handle,
349 static struct drm_file *rockchip_drm_find_drm_file(struct drm_device *drm_dev,
352 struct drm_file *file_priv;
354 /* find current process's drm_file from filelist. */
355 list_for_each_entry(file_priv, &drm_dev->filelist, lhead)
356 if (file_priv->filp == filp)
361 return ERR_PTR(-EFAULT);
364 static int rockchip_drm_gem_mmap_buffer(struct file *filp,
365 struct vm_area_struct *vma)
367 struct drm_gem_object *obj = filp->private_data;
368 struct rockchip_drm_gem_obj *rockchip_gem_obj = to_rockchip_gem_obj(obj);
369 struct drm_device *drm_dev = obj->dev;
370 struct rockchip_drm_gem_buf *buffer;
371 struct drm_file *file_priv;
372 unsigned long vm_size;
375 DRM_DEBUG_KMS("%s\n", __FILE__);
377 vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
378 vma->vm_private_data = obj;
379 vma->vm_ops = drm_dev->driver->gem_vm_ops;
381 /* restore it to driver's fops. */
382 filp->f_op = fops_get(drm_dev->driver->fops);
384 file_priv = rockchip_drm_find_drm_file(drm_dev, filp);
385 if (IS_ERR(file_priv))
386 return PTR_ERR(file_priv);
388 /* restore it to drm_file. */
389 filp->private_data = file_priv;
391 update_vm_cache_attr(rockchip_gem_obj, vma);
393 vm_size = vma->vm_end - vma->vm_start;
396 * a buffer contains information to physically continuous memory
397 * allocated by user request or at framebuffer creation.
399 buffer = rockchip_gem_obj->buffer;
401 /* check if user-requested size is valid. */
402 if (vm_size > buffer->size)
405 ret = dma_mmap_attrs(drm_dev->dev, vma, buffer->pages,
406 buffer->dma_addr, buffer->size,
409 DRM_ERROR("failed to mmap.\n");
414 * take a reference to this mapping of the object. And this reference
415 * is unreferenced by the corresponding vm_close call.
417 drm_gem_object_reference(obj);
419 drm_vm_open_locked(drm_dev, vma);
424 static const struct file_operations rockchip_drm_gem_fops = {
425 .mmap = rockchip_drm_gem_mmap_buffer,
428 int rockchip_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
429 struct drm_file *file_priv)
431 struct drm_rockchip_gem_mmap *args = data;
432 struct drm_gem_object *obj;
435 DRM_DEBUG_KMS("%s\n", __FILE__);
437 if (!(dev->driver->driver_features & DRIVER_GEM)) {
438 DRM_ERROR("does not support GEM.\n");
442 obj = drm_gem_object_lookup(dev, file_priv, args->handle);
444 DRM_ERROR("failed to lookup gem object.\n");
449 * We have to use gem object and its fops for specific mmaper,
450 * but vm_mmap() can deliver only filp. So we have to change
451 * filp->f_op and filp->private_data temporarily, then restore
452 * again. So it is important to keep lock until restoration the
453 * settings to prevent others from misuse of filp->f_op or
454 * filp->private_data.
456 mutex_lock(&dev->struct_mutex);
459 * Set specific mmper's fops. And it will be restored by
460 * rockchip_drm_gem_mmap_buffer to dev->driver->fops.
461 * This is used to call specific mapper temporarily.
463 file_priv->filp->f_op = &rockchip_drm_gem_fops;
466 * Set gem object to private_data so that specific mmaper
467 * can get the gem object. And it will be restored by
468 * rockchip_drm_gem_mmap_buffer to drm_file.
470 file_priv->filp->private_data = obj;
472 addr = vm_mmap(file_priv->filp, 0, args->size,
473 PROT_READ | PROT_WRITE, MAP_SHARED, 0);
475 drm_gem_object_unreference(obj);
477 if (IS_ERR((void *)addr)) {
478 /* check filp->f_op, filp->private_data are restored */
479 if (file_priv->filp->f_op == &rockchip_drm_gem_fops) {
480 file_priv->filp->f_op = fops_get(dev->driver->fops);
481 file_priv->filp->private_data = file_priv;
483 mutex_unlock(&dev->struct_mutex);
484 return PTR_ERR((void *)addr);
487 mutex_unlock(&dev->struct_mutex);
491 DRM_DEBUG_KMS("mapped = 0x%lx\n", (unsigned long)args->mapped);
496 int rockchip_drm_gem_get_ioctl(struct drm_device *dev, void *data,
497 struct drm_file *file_priv)
498 { struct rockchip_drm_gem_obj *rockchip_gem_obj;
499 struct drm_rockchip_gem_info *args = data;
500 struct drm_gem_object *obj;
502 mutex_lock(&dev->struct_mutex);
504 obj = drm_gem_object_lookup(dev, file_priv, args->handle);
506 DRM_ERROR("failed to lookup gem object.\n");
507 mutex_unlock(&dev->struct_mutex);
511 rockchip_gem_obj = to_rockchip_gem_obj(obj);
513 args->flags = rockchip_gem_obj->flags;
514 args->size = rockchip_gem_obj->size;
516 drm_gem_object_unreference(obj);
517 mutex_unlock(&dev->struct_mutex);
522 struct vm_area_struct *rockchip_gem_get_vma(struct vm_area_struct *vma)
524 struct vm_area_struct *vma_copy;
526 vma_copy = kmalloc(sizeof(*vma_copy), GFP_KERNEL);
530 if (vma->vm_ops && vma->vm_ops->open)
531 vma->vm_ops->open(vma);
534 get_file(vma->vm_file);
536 memcpy(vma_copy, vma, sizeof(*vma));
538 vma_copy->vm_mm = NULL;
539 vma_copy->vm_next = NULL;
540 vma_copy->vm_prev = NULL;
545 void rockchip_gem_put_vma(struct vm_area_struct *vma)
550 if (vma->vm_ops && vma->vm_ops->close)
551 vma->vm_ops->close(vma);
559 int rockchip_gem_get_pages_from_userptr(unsigned long start,
562 struct vm_area_struct *vma)
566 /* the memory region mmaped with VM_PFNMAP. */
567 if (vma_is_io(vma)) {
570 for (i = 0; i < npages; ++i, start += PAGE_SIZE) {
572 int ret = follow_pfn(vma, start, &pfn);
576 pages[i] = pfn_to_page(pfn);
580 DRM_ERROR("failed to get user_pages.\n");
587 get_npages = get_user_pages(current, current->mm, start,
588 npages, 1, 1, pages, NULL);
589 get_npages = max(get_npages, 0);
590 if (get_npages != npages) {
591 DRM_ERROR("failed to get user_pages.\n");
593 put_page(pages[--get_npages]);
600 void rockchip_gem_put_pages_to_userptr(struct page **pages,
602 struct vm_area_struct *vma)
604 if (!vma_is_io(vma)) {
607 for (i = 0; i < npages; i++) {
608 set_page_dirty_lock(pages[i]);
611 * undo the reference we took when populating
619 int rockchip_gem_map_sgt_with_dma(struct drm_device *drm_dev,
620 struct sg_table *sgt,
621 enum dma_data_direction dir)
625 mutex_lock(&drm_dev->struct_mutex);
627 nents = dma_map_sg(drm_dev->dev, sgt->sgl, sgt->nents, dir);
629 DRM_ERROR("failed to map sgl with dma.\n");
630 mutex_unlock(&drm_dev->struct_mutex);
634 mutex_unlock(&drm_dev->struct_mutex);
638 void rockchip_gem_unmap_sgt_from_dma(struct drm_device *drm_dev,
639 struct sg_table *sgt,
640 enum dma_data_direction dir)
642 dma_unmap_sg(drm_dev->dev, sgt->sgl, sgt->nents, dir);
645 int rockchip_drm_gem_init_object(struct drm_gem_object *obj)
647 DRM_DEBUG_KMS("%s\n", __FILE__);
652 void rockchip_drm_gem_free_object(struct drm_gem_object *obj)
654 struct rockchip_drm_gem_obj *rockchip_gem_obj;
655 struct rockchip_drm_gem_buf *buf;
657 DRM_DEBUG_KMS("%s\n", __FILE__);
659 rockchip_gem_obj = to_rockchip_gem_obj(obj);
660 buf = rockchip_gem_obj->buffer;
662 if (obj->import_attach)
663 drm_prime_gem_destroy(obj, buf->sgt);
665 rockchip_drm_gem_destroy(to_rockchip_gem_obj(obj));
668 int rockchip_drm_gem_dumb_create(struct drm_file *file_priv,
669 struct drm_device *dev,
670 struct drm_mode_create_dumb *args)
672 struct rockchip_drm_gem_obj *rockchip_gem_obj;
675 DRM_DEBUG_KMS("%s\n", __FILE__);
678 * alocate memory to be used for framebuffer.
679 * - this callback would be called by user application
680 * with DRM_IOCTL_MODE_CREATE_DUMB command.
683 args->pitch = args->width * ((args->bpp + 7) / 8);
684 args->size = args->pitch * args->height;
686 rockchip_gem_obj = rockchip_drm_gem_create(dev, ROCKCHIP_BO_CONTIG |
687 ROCKCHIP_BO_WC, args->size);
688 if (IS_ERR(rockchip_gem_obj))
689 return PTR_ERR(rockchip_gem_obj);
691 ret = rockchip_drm_gem_handle_create(&rockchip_gem_obj->base, file_priv,
694 rockchip_drm_gem_destroy(rockchip_gem_obj);
701 int rockchip_drm_gem_dumb_map_offset(struct drm_file *file_priv,
702 struct drm_device *dev, uint32_t handle,
705 struct drm_gem_object *obj;
708 DRM_DEBUG_KMS("%s\n", __FILE__);
710 mutex_lock(&dev->struct_mutex);
713 * get offset of memory allocated for drm framebuffer.
714 * - this callback would be called by user application
715 * with DRM_IOCTL_MODE_MAP_DUMB command.
718 obj = drm_gem_object_lookup(dev, file_priv, handle);
720 DRM_ERROR("failed to lookup gem object.\n");
725 if (!obj->map_list.map) {
726 ret = drm_gem_create_mmap_offset(obj);
731 *offset = (u64)obj->map_list.hash.key << PAGE_SHIFT;
732 DRM_DEBUG_KMS("offset = 0x%lx\n", (unsigned long)*offset);
735 drm_gem_object_unreference(obj);
737 mutex_unlock(&dev->struct_mutex);
741 int rockchip_drm_gem_dumb_destroy(struct drm_file *file_priv,
742 struct drm_device *dev,
747 DRM_DEBUG_KMS("%s\n", __FILE__);
750 * obj->refcount and obj->handle_count are decreased and
751 * if both them are 0 then rockchip_drm_gem_free_object()
752 * would be called by callback to release resources.
754 ret = drm_gem_handle_delete(file_priv, handle);
756 DRM_ERROR("failed to delete drm_gem_handle.\n");
763 int rockchip_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
765 struct drm_gem_object *obj = vma->vm_private_data;
766 struct drm_device *dev = obj->dev;
767 unsigned long f_vaddr;
771 page_offset = ((unsigned long)vmf->virtual_address -
772 vma->vm_start) >> PAGE_SHIFT;
773 f_vaddr = (unsigned long)vmf->virtual_address;
775 mutex_lock(&dev->struct_mutex);
777 ret = rockchip_drm_gem_map_buf(obj, vma, f_vaddr, page_offset);
779 DRM_ERROR("failed to map a buffer with user.\n");
781 mutex_unlock(&dev->struct_mutex);
783 return convert_to_vm_err_msg(ret);
786 int rockchip_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
788 struct rockchip_drm_gem_obj *rockchip_gem_obj;
789 struct drm_gem_object *obj;
792 DRM_DEBUG_KMS("%s\n", __FILE__);
794 /* set vm_area_struct. */
795 ret = drm_gem_mmap(filp, vma);
797 DRM_ERROR("failed to mmap.\n");
801 obj = vma->vm_private_data;
802 rockchip_gem_obj = to_rockchip_gem_obj(obj);
804 ret = check_gem_flags(rockchip_gem_obj->flags);
806 drm_gem_vm_close(vma);
807 drm_gem_free_mmap_offset(obj);
811 vma->vm_flags &= ~VM_PFNMAP;
812 vma->vm_flags |= VM_MIXEDMAP;
814 update_vm_cache_attr(rockchip_gem_obj, vma);