aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/exynos/exynos_drm_gem.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_drm_gem.c')
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gem.c79
1 files changed, 42 insertions, 37 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c
index fa1aa94a3d8e..1dffa8359f88 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c
@@ -56,9 +56,28 @@ static unsigned int convert_to_vm_err_msg(int msg)
56 return out_msg; 56 return out_msg;
57} 57}
58 58
59static unsigned int mask_gem_flags(unsigned int flags) 59static int check_gem_flags(unsigned int flags)
60{ 60{
61 return flags &= EXYNOS_BO_NONCONTIG; 61 if (flags & ~(EXYNOS_BO_MASK)) {
62 DRM_ERROR("invalid flags.\n");
63 return -EINVAL;
64 }
65
66 return 0;
67}
68
69static unsigned long roundup_gem_size(unsigned long size, unsigned int flags)
70{
71 if (!IS_NONCONTIG_BUFFER(flags)) {
72 if (size >= SZ_1M)
73 return roundup(size, SECTION_SIZE);
74 else if (size >= SZ_64K)
75 return roundup(size, SZ_64K);
76 else
77 goto out;
78 }
79out:
80 return roundup(size, PAGE_SIZE);
62} 81}
63 82
64static struct page **exynos_gem_get_pages(struct drm_gem_object *obj, 83static struct page **exynos_gem_get_pages(struct drm_gem_object *obj,
@@ -130,22 +149,12 @@ static int exynos_drm_gem_map_pages(struct drm_gem_object *obj,
130 unsigned long pfn; 149 unsigned long pfn;
131 150
132 if (exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG) { 151 if (exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG) {
133 unsigned long usize = buf->size;
134
135 if (!buf->pages) 152 if (!buf->pages)
136 return -EINTR; 153 return -EINTR;
137 154
138 while (usize > 0) { 155 pfn = page_to_pfn(buf->pages[page_offset++]);
139 pfn = page_to_pfn(buf->pages[page_offset++]); 156 } else
140 vm_insert_mixed(vma, f_vaddr, pfn); 157 pfn = (buf->dma_addr >> PAGE_SHIFT) + page_offset;
141 f_vaddr += PAGE_SIZE;
142 usize -= PAGE_SIZE;
143 }
144
145 return 0;
146 }
147
148 pfn = (buf->dma_addr >> PAGE_SHIFT) + page_offset;
149 158
150 return vm_insert_mixed(vma, f_vaddr, pfn); 159 return vm_insert_mixed(vma, f_vaddr, pfn);
151} 160}
@@ -319,10 +328,17 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
319 struct exynos_drm_gem_buf *buf; 328 struct exynos_drm_gem_buf *buf;
320 int ret; 329 int ret;
321 330
322 size = roundup(size, PAGE_SIZE); 331 if (!size) {
323 DRM_DEBUG_KMS("%s: size = 0x%lx\n", __FILE__, size); 332 DRM_ERROR("invalid size.\n");
333 return ERR_PTR(-EINVAL);
334 }
335
336 size = roundup_gem_size(size, flags);
337 DRM_DEBUG_KMS("%s\n", __FILE__);
324 338
325 flags = mask_gem_flags(flags); 339 ret = check_gem_flags(flags);
340 if (ret)
341 return ERR_PTR(ret);
326 342
327 buf = exynos_drm_init_buf(dev, size); 343 buf = exynos_drm_init_buf(dev, size);
328 if (!buf) 344 if (!buf)
@@ -331,7 +347,7 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
331 exynos_gem_obj = exynos_drm_gem_init(dev, size); 347 exynos_gem_obj = exynos_drm_gem_init(dev, size);
332 if (!exynos_gem_obj) { 348 if (!exynos_gem_obj) {
333 ret = -ENOMEM; 349 ret = -ENOMEM;
334 goto err; 350 goto err_fini_buf;
335 } 351 }
336 352
337 exynos_gem_obj->buffer = buf; 353 exynos_gem_obj->buffer = buf;
@@ -347,18 +363,19 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
347 ret = exynos_drm_gem_get_pages(&exynos_gem_obj->base); 363 ret = exynos_drm_gem_get_pages(&exynos_gem_obj->base);
348 if (ret < 0) { 364 if (ret < 0) {
349 drm_gem_object_release(&exynos_gem_obj->base); 365 drm_gem_object_release(&exynos_gem_obj->base);
350 goto err; 366 goto err_fini_buf;
351 } 367 }
352 } else { 368 } else {
353 ret = exynos_drm_alloc_buf(dev, buf, flags); 369 ret = exynos_drm_alloc_buf(dev, buf, flags);
354 if (ret < 0) { 370 if (ret < 0) {
355 drm_gem_object_release(&exynos_gem_obj->base); 371 drm_gem_object_release(&exynos_gem_obj->base);
356 goto err; 372 goto err_fini_buf;
357 } 373 }
358 } 374 }
359 375
360 return exynos_gem_obj; 376 return exynos_gem_obj;
361err: 377
378err_fini_buf:
362 exynos_drm_fini_buf(dev, buf); 379 exynos_drm_fini_buf(dev, buf);
363 return ERR_PTR(ret); 380 return ERR_PTR(ret);
364} 381}
@@ -497,6 +514,8 @@ static int exynos_drm_gem_mmap_buffer(struct file *filp,
497 if (!buffer->pages) 514 if (!buffer->pages)
498 return -EINVAL; 515 return -EINVAL;
499 516
517 vma->vm_flags |= VM_MIXEDMAP;
518
500 do { 519 do {
501 ret = vm_insert_page(vma, uaddr, buffer->pages[i++]); 520 ret = vm_insert_page(vma, uaddr, buffer->pages[i++]);
502 if (ret) { 521 if (ret) {
@@ -554,10 +573,8 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
554 obj->filp->f_op = &exynos_drm_gem_fops; 573 obj->filp->f_op = &exynos_drm_gem_fops;
555 obj->filp->private_data = obj; 574 obj->filp->private_data = obj;
556 575
557 down_write(&current->mm->mmap_sem); 576 addr = vm_mmap(obj->filp, 0, args->size,
558 addr = do_mmap(obj->filp, 0, args->size,
559 PROT_READ | PROT_WRITE, MAP_SHARED, 0); 577 PROT_READ | PROT_WRITE, MAP_SHARED, 0);
560 up_write(&current->mm->mmap_sem);
561 578
562 drm_gem_object_unreference_unlocked(obj); 579 drm_gem_object_unreference_unlocked(obj);
563 580
@@ -685,7 +702,6 @@ int exynos_drm_gem_dumb_destroy(struct drm_file *file_priv,
685int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) 702int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
686{ 703{
687 struct drm_gem_object *obj = vma->vm_private_data; 704 struct drm_gem_object *obj = vma->vm_private_data;
688 struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);
689 struct drm_device *dev = obj->dev; 705 struct drm_device *dev = obj->dev;
690 unsigned long f_vaddr; 706 unsigned long f_vaddr;
691 pgoff_t page_offset; 707 pgoff_t page_offset;
@@ -697,21 +713,10 @@ int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
697 713
698 mutex_lock(&dev->struct_mutex); 714 mutex_lock(&dev->struct_mutex);
699 715
700 /*
701 * allocate all pages as desired size if user wants to allocate
702 * physically non-continuous memory.
703 */
704 if (exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG) {
705 ret = exynos_drm_gem_get_pages(obj);
706 if (ret < 0)
707 goto err;
708 }
709
710 ret = exynos_drm_gem_map_pages(obj, vma, f_vaddr, page_offset); 716 ret = exynos_drm_gem_map_pages(obj, vma, f_vaddr, page_offset);
711 if (ret < 0) 717 if (ret < 0)
712 DRM_ERROR("failed to map pages.\n"); 718 DRM_ERROR("failed to map pages.\n");
713 719
714err:
715 mutex_unlock(&dev->struct_mutex); 720 mutex_unlock(&dev->struct_mutex);
716 721
717 return convert_to_vm_err_msg(ret); 722 return convert_to_vm_err_msg(ret);