drm/exynos: add vm_ops to specific gem mmaper
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / drm / exynos / exynos_drm_gem.c
1 /* exynos_drm_gem.c
2  *
3  * Copyright (c) 2011 Samsung Electronics Co., Ltd.
4  * Author: Inki Dae <inki.dae@samsung.com>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the next
14  * paragraph) shall be included in all copies or substantial portions of the
15  * Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23  * OTHER DEALINGS IN THE SOFTWARE.
24  */
25
26 #include <drm/drmP.h>
27
28 #include <linux/shmem_fs.h>
29 #include <drm/exynos_drm.h>
30
31 #include "exynos_drm_drv.h"
32 #include "exynos_drm_gem.h"
33 #include "exynos_drm_buf.h"
34
35 static unsigned int convert_to_vm_err_msg(int msg)
36 {
37         unsigned int out_msg;
38
39         switch (msg) {
40         case 0:
41         case -ERESTARTSYS:
42         case -EINTR:
43                 out_msg = VM_FAULT_NOPAGE;
44                 break;
45
46         case -ENOMEM:
47                 out_msg = VM_FAULT_OOM;
48                 break;
49
50         default:
51                 out_msg = VM_FAULT_SIGBUS;
52                 break;
53         }
54
55         return out_msg;
56 }
57
58 static int check_gem_flags(unsigned int flags)
59 {
60         if (flags & ~(EXYNOS_BO_MASK)) {
61                 DRM_ERROR("invalid flags.\n");
62                 return -EINVAL;
63         }
64
65         return 0;
66 }
67
68 static void update_vm_cache_attr(struct exynos_drm_gem_obj *obj,
69                                         struct vm_area_struct *vma)
70 {
71         DRM_DEBUG_KMS("flags = 0x%x\n", obj->flags);
72
73         /* non-cachable as default. */
74         if (obj->flags & EXYNOS_BO_CACHABLE)
75                 vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
76         else if (obj->flags & EXYNOS_BO_WC)
77                 vma->vm_page_prot =
78                         pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
79         else
80                 vma->vm_page_prot =
81                         pgprot_noncached(vm_get_page_prot(vma->vm_flags));
82 }
83
84 static unsigned long roundup_gem_size(unsigned long size, unsigned int flags)
85 {
86         /* TODO */
87
88         return roundup(size, PAGE_SIZE);
89 }
90
91 static int exynos_drm_gem_map_buf(struct drm_gem_object *obj,
92                                         struct vm_area_struct *vma,
93                                         unsigned long f_vaddr,
94                                         pgoff_t page_offset)
95 {
96         struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);
97         struct exynos_drm_gem_buf *buf = exynos_gem_obj->buffer;
98         struct scatterlist *sgl;
99         unsigned long pfn;
100         int i;
101
102         if (exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG) {
103                 if (!buf->sgt)
104                         return -EINTR;
105
106                 sgl = buf->sgt->sgl;
107                 for_each_sg(buf->sgt->sgl, sgl, buf->sgt->nents, i) {
108                         if (!sgl) {
109                                 DRM_ERROR("invalid SG table\n");
110                                 return -EINTR;
111                         }
112                         if (page_offset < (sgl->length >> PAGE_SHIFT))
113                                 break;
114                         page_offset -=  (sgl->length >> PAGE_SHIFT);
115                 }
116
117                 if (i >= buf->sgt->nents) {
118                         DRM_ERROR("invalid page offset\n");
119                         return -EINVAL;
120                 }
121
122                 pfn = __phys_to_pfn(sg_phys(sgl)) + page_offset;
123         } else {
124                 if (!buf->pages)
125                         return -EINTR;
126
127                 pfn = page_to_pfn(buf->pages[0]) + page_offset;
128         }
129
130         return vm_insert_mixed(vma, f_vaddr, pfn);
131 }
132
133 static int exynos_drm_gem_handle_create(struct drm_gem_object *obj,
134                                         struct drm_file *file_priv,
135                                         unsigned int *handle)
136 {
137         int ret;
138
139         /*
140          * allocate a id of idr table where the obj is registered
141          * and handle has the id what user can see.
142          */
143         ret = drm_gem_handle_create(file_priv, obj, handle);
144         if (ret)
145                 return ret;
146
147         DRM_DEBUG_KMS("gem handle = 0x%x\n", *handle);
148
149         /* drop reference from allocate - handle holds it now. */
150         drm_gem_object_unreference_unlocked(obj);
151
152         return 0;
153 }
154
155 void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj)
156 {
157         struct drm_gem_object *obj;
158         struct exynos_drm_gem_buf *buf;
159
160         DRM_DEBUG_KMS("%s\n", __FILE__);
161
162         obj = &exynos_gem_obj->base;
163         buf = exynos_gem_obj->buffer;
164
165         DRM_DEBUG_KMS("handle count = %d\n", atomic_read(&obj->handle_count));
166
167         /*
168          * do not release memory region from exporter.
169          *
170          * the region will be released by exporter
171          * once dmabuf's refcount becomes 0.
172          */
173         if (obj->import_attach)
174                 goto out;
175
176         exynos_drm_free_buf(obj->dev, exynos_gem_obj->flags, buf);
177
178 out:
179         exynos_drm_fini_buf(obj->dev, buf);
180         exynos_gem_obj->buffer = NULL;
181
182         if (obj->map_list.map)
183                 drm_gem_free_mmap_offset(obj);
184
185         /* release file pointer to gem object. */
186         drm_gem_object_release(obj);
187
188         kfree(exynos_gem_obj);
189         exynos_gem_obj = NULL;
190 }
191
192 struct exynos_drm_gem_obj *exynos_drm_gem_init(struct drm_device *dev,
193                                                       unsigned long size)
194 {
195         struct exynos_drm_gem_obj *exynos_gem_obj;
196         struct drm_gem_object *obj;
197         int ret;
198
199         exynos_gem_obj = kzalloc(sizeof(*exynos_gem_obj), GFP_KERNEL);
200         if (!exynos_gem_obj) {
201                 DRM_ERROR("failed to allocate exynos gem object\n");
202                 return NULL;
203         }
204
205         exynos_gem_obj->size = size;
206         obj = &exynos_gem_obj->base;
207
208         ret = drm_gem_object_init(dev, obj, size);
209         if (ret < 0) {
210                 DRM_ERROR("failed to initialize gem object\n");
211                 kfree(exynos_gem_obj);
212                 return NULL;
213         }
214
215         DRM_DEBUG_KMS("created file object = 0x%x\n", (unsigned int)obj->filp);
216
217         return exynos_gem_obj;
218 }
219
220 struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
221                                                 unsigned int flags,
222                                                 unsigned long size)
223 {
224         struct exynos_drm_gem_obj *exynos_gem_obj;
225         struct exynos_drm_gem_buf *buf;
226         int ret;
227
228         if (!size) {
229                 DRM_ERROR("invalid size.\n");
230                 return ERR_PTR(-EINVAL);
231         }
232
233         size = roundup_gem_size(size, flags);
234         DRM_DEBUG_KMS("%s\n", __FILE__);
235
236         ret = check_gem_flags(flags);
237         if (ret)
238                 return ERR_PTR(ret);
239
240         buf = exynos_drm_init_buf(dev, size);
241         if (!buf)
242                 return ERR_PTR(-ENOMEM);
243
244         exynos_gem_obj = exynos_drm_gem_init(dev, size);
245         if (!exynos_gem_obj) {
246                 ret = -ENOMEM;
247                 goto err_fini_buf;
248         }
249
250         exynos_gem_obj->buffer = buf;
251
252         /* set memory type and cache attribute from user side. */
253         exynos_gem_obj->flags = flags;
254
255         ret = exynos_drm_alloc_buf(dev, buf, flags);
256         if (ret < 0) {
257                 drm_gem_object_release(&exynos_gem_obj->base);
258                 goto err_fini_buf;
259         }
260
261         return exynos_gem_obj;
262
263 err_fini_buf:
264         exynos_drm_fini_buf(dev, buf);
265         return ERR_PTR(ret);
266 }
267
268 int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data,
269                                 struct drm_file *file_priv)
270 {
271         struct drm_exynos_gem_create *args = data;
272         struct exynos_drm_gem_obj *exynos_gem_obj;
273         int ret;
274
275         DRM_DEBUG_KMS("%s\n", __FILE__);
276
277         exynos_gem_obj = exynos_drm_gem_create(dev, args->flags, args->size);
278         if (IS_ERR(exynos_gem_obj))
279                 return PTR_ERR(exynos_gem_obj);
280
281         ret = exynos_drm_gem_handle_create(&exynos_gem_obj->base, file_priv,
282                         &args->handle);
283         if (ret) {
284                 exynos_drm_gem_destroy(exynos_gem_obj);
285                 return ret;
286         }
287
288         return 0;
289 }
290
291 dma_addr_t *exynos_drm_gem_get_dma_addr(struct drm_device *dev,
292                                         unsigned int gem_handle,
293                                         struct drm_file *filp)
294 {
295         struct exynos_drm_gem_obj *exynos_gem_obj;
296         struct drm_gem_object *obj;
297
298         obj = drm_gem_object_lookup(dev, filp, gem_handle);
299         if (!obj) {
300                 DRM_ERROR("failed to lookup gem object.\n");
301                 return ERR_PTR(-EINVAL);
302         }
303
304         exynos_gem_obj = to_exynos_gem_obj(obj);
305
306         return &exynos_gem_obj->buffer->dma_addr;
307 }
308
309 void exynos_drm_gem_put_dma_addr(struct drm_device *dev,
310                                         unsigned int gem_handle,
311                                         struct drm_file *filp)
312 {
313         struct exynos_drm_gem_obj *exynos_gem_obj;
314         struct drm_gem_object *obj;
315
316         obj = drm_gem_object_lookup(dev, filp, gem_handle);
317         if (!obj) {
318                 DRM_ERROR("failed to lookup gem object.\n");
319                 return;
320         }
321
322         exynos_gem_obj = to_exynos_gem_obj(obj);
323
324         drm_gem_object_unreference_unlocked(obj);
325
326         /*
327          * decrease obj->refcount one more time because we has already
328          * increased it at exynos_drm_gem_get_dma_addr().
329          */
330         drm_gem_object_unreference_unlocked(obj);
331 }
332
333 int exynos_drm_gem_map_offset_ioctl(struct drm_device *dev, void *data,
334                                     struct drm_file *file_priv)
335 {
336         struct drm_exynos_gem_map_off *args = data;
337
338         DRM_DEBUG_KMS("%s\n", __FILE__);
339
340         DRM_DEBUG_KMS("handle = 0x%x, offset = 0x%lx\n",
341                         args->handle, (unsigned long)args->offset);
342
343         if (!(dev->driver->driver_features & DRIVER_GEM)) {
344                 DRM_ERROR("does not support GEM.\n");
345                 return -ENODEV;
346         }
347
348         return exynos_drm_gem_dumb_map_offset(file_priv, dev, args->handle,
349                         &args->offset);
350 }
351
352 static struct drm_file *exynos_drm_find_drm_file(struct drm_device *drm_dev,
353                                                         struct file *filp)
354 {
355         struct drm_file *file_priv;
356
357         mutex_lock(&drm_dev->struct_mutex);
358
359         /* find current process's drm_file from filelist. */
360         list_for_each_entry(file_priv, &drm_dev->filelist, lhead) {
361                 if (file_priv->filp == filp) {
362                         mutex_unlock(&drm_dev->struct_mutex);
363                         return file_priv;
364                 }
365         }
366
367         mutex_unlock(&drm_dev->struct_mutex);
368         WARN_ON(1);
369
370         return ERR_PTR(-EFAULT);
371 }
372
373 static int exynos_drm_gem_mmap_buffer(struct file *filp,
374                                       struct vm_area_struct *vma)
375 {
376         struct drm_gem_object *obj = filp->private_data;
377         struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);
378         struct drm_device *drm_dev = obj->dev;
379         struct exynos_drm_gem_buf *buffer;
380         struct drm_file *file_priv;
381         unsigned long vm_size;
382         int ret;
383
384         DRM_DEBUG_KMS("%s\n", __FILE__);
385
386         vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
387         vma->vm_private_data = obj;
388         vma->vm_ops = drm_dev->driver->gem_vm_ops;
389
390         /* restore it to driver's fops. */
391         filp->f_op = fops_get(drm_dev->driver->fops);
392
393         file_priv = exynos_drm_find_drm_file(drm_dev, filp);
394         if (IS_ERR(file_priv))
395                 return PTR_ERR(file_priv);
396
397         /* restore it to drm_file. */
398         filp->private_data = file_priv;
399
400         update_vm_cache_attr(exynos_gem_obj, vma);
401
402         vm_size = vma->vm_end - vma->vm_start;
403
404         /*
405          * a buffer contains information to physically continuous memory
406          * allocated by user request or at framebuffer creation.
407          */
408         buffer = exynos_gem_obj->buffer;
409
410         /* check if user-requested size is valid. */
411         if (vm_size > buffer->size)
412                 return -EINVAL;
413
414         ret = dma_mmap_attrs(drm_dev->dev, vma, buffer->kvaddr,
415                                 buffer->dma_addr, buffer->size,
416                                 &buffer->dma_attrs);
417         if (ret < 0) {
418                 DRM_ERROR("failed to mmap.\n");
419                 return ret;
420         }
421
422         /*
423          * take a reference to this mapping of the object. And this reference
424          * is unreferenced by the corresponding vm_close call.
425          */
426         drm_gem_object_reference(obj);
427
428         mutex_lock(&drm_dev->struct_mutex);
429         drm_vm_open_locked(drm_dev, vma);
430         mutex_unlock(&drm_dev->struct_mutex);
431
432         return 0;
433 }
434
435 static const struct file_operations exynos_drm_gem_fops = {
436         .mmap = exynos_drm_gem_mmap_buffer,
437 };
438
439 int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
440                               struct drm_file *file_priv)
441 {
442         struct drm_exynos_gem_mmap *args = data;
443         struct drm_gem_object *obj;
444         unsigned int addr;
445
446         DRM_DEBUG_KMS("%s\n", __FILE__);
447
448         if (!(dev->driver->driver_features & DRIVER_GEM)) {
449                 DRM_ERROR("does not support GEM.\n");
450                 return -ENODEV;
451         }
452
453         obj = drm_gem_object_lookup(dev, file_priv, args->handle);
454         if (!obj) {
455                 DRM_ERROR("failed to lookup gem object.\n");
456                 return -EINVAL;
457         }
458
459         /*
460          * Set specific mmper's fops. And it will be restored by
461          * exynos_drm_gem_mmap_buffer to dev->driver->fops.
462          * This is used to call specific mapper temporarily.
463          */
464         file_priv->filp->f_op = &exynos_drm_gem_fops;
465
466         /*
467          * Set gem object to private_data so that specific mmaper
468          * can get the gem object. And it will be restored by
469          * exynos_drm_gem_mmap_buffer to drm_file.
470          */
471         file_priv->filp->private_data = obj;
472
473         addr = vm_mmap(file_priv->filp, 0, args->size,
474                         PROT_READ | PROT_WRITE, MAP_SHARED, 0);
475
476         drm_gem_object_unreference_unlocked(obj);
477
478         if (IS_ERR((void *)addr)) {
479                 file_priv->filp->private_data = file_priv;
480                 return PTR_ERR((void *)addr);
481         }
482
483         args->mapped = addr;
484
485         DRM_DEBUG_KMS("mapped = 0x%lx\n", (unsigned long)args->mapped);
486
487         return 0;
488 }
489
490 int exynos_drm_gem_get_ioctl(struct drm_device *dev, void *data,
491                                       struct drm_file *file_priv)
492 {       struct exynos_drm_gem_obj *exynos_gem_obj;
493         struct drm_exynos_gem_info *args = data;
494         struct drm_gem_object *obj;
495
496         mutex_lock(&dev->struct_mutex);
497
498         obj = drm_gem_object_lookup(dev, file_priv, args->handle);
499         if (!obj) {
500                 DRM_ERROR("failed to lookup gem object.\n");
501                 mutex_unlock(&dev->struct_mutex);
502                 return -EINVAL;
503         }
504
505         exynos_gem_obj = to_exynos_gem_obj(obj);
506
507         args->flags = exynos_gem_obj->flags;
508         args->size = exynos_gem_obj->size;
509
510         drm_gem_object_unreference(obj);
511         mutex_unlock(&dev->struct_mutex);
512
513         return 0;
514 }
515
516 struct vm_area_struct *exynos_gem_get_vma(struct vm_area_struct *vma)
517 {
518         struct vm_area_struct *vma_copy;
519
520         vma_copy = kmalloc(sizeof(*vma_copy), GFP_KERNEL);
521         if (!vma_copy)
522                 return NULL;
523
524         if (vma->vm_ops && vma->vm_ops->open)
525                 vma->vm_ops->open(vma);
526
527         if (vma->vm_file)
528                 get_file(vma->vm_file);
529
530         memcpy(vma_copy, vma, sizeof(*vma));
531
532         vma_copy->vm_mm = NULL;
533         vma_copy->vm_next = NULL;
534         vma_copy->vm_prev = NULL;
535
536         return vma_copy;
537 }
538
539 void exynos_gem_put_vma(struct vm_area_struct *vma)
540 {
541         if (!vma)
542                 return;
543
544         if (vma->vm_ops && vma->vm_ops->close)
545                 vma->vm_ops->close(vma);
546
547         if (vma->vm_file)
548                 fput(vma->vm_file);
549
550         kfree(vma);
551 }
552
553 int exynos_gem_get_pages_from_userptr(unsigned long start,
554                                                 unsigned int npages,
555                                                 struct page **pages,
556                                                 struct vm_area_struct *vma)
557 {
558         int get_npages;
559
560         /* the memory region mmaped with VM_PFNMAP. */
561         if (vma_is_io(vma)) {
562                 unsigned int i;
563
564                 for (i = 0; i < npages; ++i, start += PAGE_SIZE) {
565                         unsigned long pfn;
566                         int ret = follow_pfn(vma, start, &pfn);
567                         if (ret)
568                                 return ret;
569
570                         pages[i] = pfn_to_page(pfn);
571                 }
572
573                 if (i != npages) {
574                         DRM_ERROR("failed to get user_pages.\n");
575                         return -EINVAL;
576                 }
577
578                 return 0;
579         }
580
581         get_npages = get_user_pages(current, current->mm, start,
582                                         npages, 1, 1, pages, NULL);
583         get_npages = max(get_npages, 0);
584         if (get_npages != npages) {
585                 DRM_ERROR("failed to get user_pages.\n");
586                 while (get_npages)
587                         put_page(pages[--get_npages]);
588                 return -EFAULT;
589         }
590
591         return 0;
592 }
593
594 void exynos_gem_put_pages_to_userptr(struct page **pages,
595                                         unsigned int npages,
596                                         struct vm_area_struct *vma)
597 {
598         if (!vma_is_io(vma)) {
599                 unsigned int i;
600
601                 for (i = 0; i < npages; i++) {
602                         set_page_dirty_lock(pages[i]);
603
604                         /*
605                          * undo the reference we took when populating
606                          * the table.
607                          */
608                         put_page(pages[i]);
609                 }
610         }
611 }
612
613 int exynos_gem_map_sgt_with_dma(struct drm_device *drm_dev,
614                                 struct sg_table *sgt,
615                                 enum dma_data_direction dir)
616 {
617         int nents;
618
619         mutex_lock(&drm_dev->struct_mutex);
620
621         nents = dma_map_sg(drm_dev->dev, sgt->sgl, sgt->nents, dir);
622         if (!nents) {
623                 DRM_ERROR("failed to map sgl with dma.\n");
624                 mutex_unlock(&drm_dev->struct_mutex);
625                 return nents;
626         }
627
628         mutex_unlock(&drm_dev->struct_mutex);
629         return 0;
630 }
631
632 void exynos_gem_unmap_sgt_from_dma(struct drm_device *drm_dev,
633                                 struct sg_table *sgt,
634                                 enum dma_data_direction dir)
635 {
636         dma_unmap_sg(drm_dev->dev, sgt->sgl, sgt->nents, dir);
637 }
638
639 int exynos_drm_gem_init_object(struct drm_gem_object *obj)
640 {
641         DRM_DEBUG_KMS("%s\n", __FILE__);
642
643         return 0;
644 }
645
646 void exynos_drm_gem_free_object(struct drm_gem_object *obj)
647 {
648         struct exynos_drm_gem_obj *exynos_gem_obj;
649         struct exynos_drm_gem_buf *buf;
650
651         DRM_DEBUG_KMS("%s\n", __FILE__);
652
653         exynos_gem_obj = to_exynos_gem_obj(obj);
654         buf = exynos_gem_obj->buffer;
655
656         if (obj->import_attach)
657                 drm_prime_gem_destroy(obj, buf->sgt);
658
659         exynos_drm_gem_destroy(to_exynos_gem_obj(obj));
660 }
661
662 int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
663                                struct drm_device *dev,
664                                struct drm_mode_create_dumb *args)
665 {
666         struct exynos_drm_gem_obj *exynos_gem_obj;
667         int ret;
668
669         DRM_DEBUG_KMS("%s\n", __FILE__);
670
671         /*
672          * alocate memory to be used for framebuffer.
673          * - this callback would be called by user application
674          *      with DRM_IOCTL_MODE_CREATE_DUMB command.
675          */
676
677         args->pitch = args->width * ((args->bpp + 7) / 8);
678         args->size = args->pitch * args->height;
679
680         exynos_gem_obj = exynos_drm_gem_create(dev, args->flags, args->size);
681         if (IS_ERR(exynos_gem_obj))
682                 return PTR_ERR(exynos_gem_obj);
683
684         ret = exynos_drm_gem_handle_create(&exynos_gem_obj->base, file_priv,
685                         &args->handle);
686         if (ret) {
687                 exynos_drm_gem_destroy(exynos_gem_obj);
688                 return ret;
689         }
690
691         return 0;
692 }
693
694 int exynos_drm_gem_dumb_map_offset(struct drm_file *file_priv,
695                                    struct drm_device *dev, uint32_t handle,
696                                    uint64_t *offset)
697 {
698         struct drm_gem_object *obj;
699         int ret = 0;
700
701         DRM_DEBUG_KMS("%s\n", __FILE__);
702
703         mutex_lock(&dev->struct_mutex);
704
705         /*
706          * get offset of memory allocated for drm framebuffer.
707          * - this callback would be called by user application
708          *      with DRM_IOCTL_MODE_MAP_DUMB command.
709          */
710
711         obj = drm_gem_object_lookup(dev, file_priv, handle);
712         if (!obj) {
713                 DRM_ERROR("failed to lookup gem object.\n");
714                 ret = -EINVAL;
715                 goto unlock;
716         }
717
718         if (!obj->map_list.map) {
719                 ret = drm_gem_create_mmap_offset(obj);
720                 if (ret)
721                         goto out;
722         }
723
724         *offset = (u64)obj->map_list.hash.key << PAGE_SHIFT;
725         DRM_DEBUG_KMS("offset = 0x%lx\n", (unsigned long)*offset);
726
727 out:
728         drm_gem_object_unreference(obj);
729 unlock:
730         mutex_unlock(&dev->struct_mutex);
731         return ret;
732 }
733
734 int exynos_drm_gem_dumb_destroy(struct drm_file *file_priv,
735                                 struct drm_device *dev,
736                                 unsigned int handle)
737 {
738         int ret;
739
740         DRM_DEBUG_KMS("%s\n", __FILE__);
741
742         /*
743          * obj->refcount and obj->handle_count are decreased and
744          * if both them are 0 then exynos_drm_gem_free_object()
745          * would be called by callback to release resources.
746          */
747         ret = drm_gem_handle_delete(file_priv, handle);
748         if (ret < 0) {
749                 DRM_ERROR("failed to delete drm_gem_handle.\n");
750                 return ret;
751         }
752
753         return 0;
754 }
755
756 int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
757 {
758         struct drm_gem_object *obj = vma->vm_private_data;
759         struct drm_device *dev = obj->dev;
760         unsigned long f_vaddr;
761         pgoff_t page_offset;
762         int ret;
763
764         page_offset = ((unsigned long)vmf->virtual_address -
765                         vma->vm_start) >> PAGE_SHIFT;
766         f_vaddr = (unsigned long)vmf->virtual_address;
767
768         mutex_lock(&dev->struct_mutex);
769
770         ret = exynos_drm_gem_map_buf(obj, vma, f_vaddr, page_offset);
771         if (ret < 0)
772                 DRM_ERROR("failed to map a buffer with user.\n");
773
774         mutex_unlock(&dev->struct_mutex);
775
776         return convert_to_vm_err_msg(ret);
777 }
778
779 int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
780 {
781         struct exynos_drm_gem_obj *exynos_gem_obj;
782         struct drm_gem_object *obj;
783         int ret;
784
785         DRM_DEBUG_KMS("%s\n", __FILE__);
786
787         /* set vm_area_struct. */
788         ret = drm_gem_mmap(filp, vma);
789         if (ret < 0) {
790                 DRM_ERROR("failed to mmap.\n");
791                 return ret;
792         }
793
794         obj = vma->vm_private_data;
795         exynos_gem_obj = to_exynos_gem_obj(obj);
796
797         ret = check_gem_flags(exynos_gem_obj->flags);
798         if (ret) {
799                 drm_gem_vm_close(vma);
800                 drm_gem_free_mmap_offset(obj);
801                 return ret;
802         }
803
804         vma->vm_flags &= ~VM_PFNMAP;
805         vma->vm_flags |= VM_MIXEDMAP;
806
807         update_vm_cache_attr(exynos_gem_obj, vma);
808
809         return ret;
810 }