diff options
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_gem.c | 49 | ||||
-rw-r--r-- | include/drm/exynos_drm.h | 11 |
2 files changed, 49 insertions, 11 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c index 1dffa8359f88..e8ab3beb4510 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c | |||
@@ -66,6 +66,22 @@ static int check_gem_flags(unsigned int flags) | |||
66 | return 0; | 66 | return 0; |
67 | } | 67 | } |
68 | 68 | ||
69 | static void update_vm_cache_attr(struct exynos_drm_gem_obj *obj, | ||
70 | struct vm_area_struct *vma) | ||
71 | { | ||
72 | DRM_DEBUG_KMS("flags = 0x%x\n", obj->flags); | ||
73 | |||
74 | /* non-cachable as default. */ | ||
75 | if (obj->flags & EXYNOS_BO_CACHABLE) | ||
76 | vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); | ||
77 | else if (obj->flags & EXYNOS_BO_WC) | ||
78 | vma->vm_page_prot = | ||
79 | pgprot_writecombine(vm_get_page_prot(vma->vm_flags)); | ||
80 | else | ||
81 | vma->vm_page_prot = | ||
82 | pgprot_noncached(vm_get_page_prot(vma->vm_flags)); | ||
83 | } | ||
84 | |||
69 | static unsigned long roundup_gem_size(unsigned long size, unsigned int flags) | 85 | static unsigned long roundup_gem_size(unsigned long size, unsigned int flags) |
70 | { | 86 | { |
71 | if (!IS_NONCONTIG_BUFFER(flags)) { | 87 | if (!IS_NONCONTIG_BUFFER(flags)) { |
@@ -262,24 +278,24 @@ static int exynos_drm_gem_handle_create(struct drm_gem_object *obj, | |||
262 | void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj) | 278 | void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj) |
263 | { | 279 | { |
264 | struct drm_gem_object *obj; | 280 | struct drm_gem_object *obj; |
281 | struct exynos_drm_gem_buf *buf; | ||
265 | 282 | ||
266 | DRM_DEBUG_KMS("%s\n", __FILE__); | 283 | DRM_DEBUG_KMS("%s\n", __FILE__); |
267 | 284 | ||
268 | if (!exynos_gem_obj) | ||
269 | return; | ||
270 | |||
271 | obj = &exynos_gem_obj->base; | 285 | obj = &exynos_gem_obj->base; |
286 | buf = exynos_gem_obj->buffer; | ||
272 | 287 | ||
273 | DRM_DEBUG_KMS("handle count = %d\n", atomic_read(&obj->handle_count)); | 288 | DRM_DEBUG_KMS("handle count = %d\n", atomic_read(&obj->handle_count)); |
274 | 289 | ||
275 | if ((exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG) && | 290 | if (!buf->pages) |
276 | exynos_gem_obj->buffer->pages) | 291 | return; |
292 | |||
293 | if (exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG) | ||
277 | exynos_drm_gem_put_pages(obj); | 294 | exynos_drm_gem_put_pages(obj); |
278 | else | 295 | else |
279 | exynos_drm_free_buf(obj->dev, exynos_gem_obj->flags, | 296 | exynos_drm_free_buf(obj->dev, exynos_gem_obj->flags, buf); |
280 | exynos_gem_obj->buffer); | ||
281 | 297 | ||
282 | exynos_drm_fini_buf(obj->dev, exynos_gem_obj->buffer); | 298 | exynos_drm_fini_buf(obj->dev, buf); |
283 | exynos_gem_obj->buffer = NULL; | 299 | exynos_gem_obj->buffer = NULL; |
284 | 300 | ||
285 | if (obj->map_list.map) | 301 | if (obj->map_list.map) |
@@ -493,8 +509,7 @@ static int exynos_drm_gem_mmap_buffer(struct file *filp, | |||
493 | 509 | ||
494 | vma->vm_flags |= (VM_IO | VM_RESERVED); | 510 | vma->vm_flags |= (VM_IO | VM_RESERVED); |
495 | 511 | ||
496 | /* in case of direct mapping, always having non-cachable attribute */ | 512 | update_vm_cache_attr(exynos_gem_obj, vma); |
497 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | ||
498 | 513 | ||
499 | vm_size = usize = vma->vm_end - vma->vm_start; | 514 | vm_size = usize = vma->vm_end - vma->vm_start; |
500 | 515 | ||
@@ -724,6 +739,8 @@ int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
724 | 739 | ||
725 | int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) | 740 | int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) |
726 | { | 741 | { |
742 | struct exynos_drm_gem_obj *exynos_gem_obj; | ||
743 | struct drm_gem_object *obj; | ||
727 | int ret; | 744 | int ret; |
728 | 745 | ||
729 | DRM_DEBUG_KMS("%s\n", __FILE__); | 746 | DRM_DEBUG_KMS("%s\n", __FILE__); |
@@ -735,8 +752,20 @@ int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) | |||
735 | return ret; | 752 | return ret; |
736 | } | 753 | } |
737 | 754 | ||
755 | obj = vma->vm_private_data; | ||
756 | exynos_gem_obj = to_exynos_gem_obj(obj); | ||
757 | |||
758 | ret = check_gem_flags(exynos_gem_obj->flags); | ||
759 | if (ret) { | ||
760 | drm_gem_vm_close(vma); | ||
761 | drm_gem_free_mmap_offset(obj); | ||
762 | return ret; | ||
763 | } | ||
764 | |||
738 | vma->vm_flags &= ~VM_PFNMAP; | 765 | vma->vm_flags &= ~VM_PFNMAP; |
739 | vma->vm_flags |= VM_MIXEDMAP; | 766 | vma->vm_flags |= VM_MIXEDMAP; |
740 | 767 | ||
768 | update_vm_cache_attr(exynos_gem_obj, vma); | ||
769 | |||
741 | return ret; | 770 | return ret; |
742 | } | 771 | } |
diff --git a/include/drm/exynos_drm.h b/include/drm/exynos_drm.h index e478de4e5d56..2d6eb06637bf 100644 --- a/include/drm/exynos_drm.h +++ b/include/drm/exynos_drm.h | |||
@@ -95,9 +95,18 @@ struct drm_exynos_plane_set_zpos { | |||
95 | 95 | ||
96 | /* memory type definitions. */ | 96 | /* memory type definitions. */ |
97 | enum e_drm_exynos_gem_mem_type { | 97 | enum e_drm_exynos_gem_mem_type { |
98 | /* Physically Continuous memory and used as default. */ | ||
99 | EXYNOS_BO_CONTIG = 0 << 0, | ||
98 | /* Physically Non-Continuous memory. */ | 100 | /* Physically Non-Continuous memory. */ |
99 | EXYNOS_BO_NONCONTIG = 1 << 0, | 101 | EXYNOS_BO_NONCONTIG = 1 << 0, |
100 | EXYNOS_BO_MASK = EXYNOS_BO_NONCONTIG | 102 | /* non-cachable mapping and used as default. */ |
103 | EXYNOS_BO_NONCACHABLE = 0 << 1, | ||
104 | /* cachable mapping. */ | ||
105 | EXYNOS_BO_CACHABLE = 1 << 1, | ||
106 | /* write-combine mapping. */ | ||
107 | EXYNOS_BO_WC = 1 << 2, | ||
108 | EXYNOS_BO_MASK = EXYNOS_BO_NONCONTIG | EXYNOS_BO_CACHABLE | | ||
109 | EXYNOS_BO_WC | ||
101 | }; | 110 | }; |
102 | 111 | ||
103 | #define DRM_EXYNOS_GEM_CREATE 0x00 | 112 | #define DRM_EXYNOS_GEM_CREATE 0x00 |