blob: 077de014d61017d77853c41a7e5a2d4084e092f1 [file] [log] [blame]
Inki Dae1c248b72011-10-04 19:19:01 +09001/* exynos_drm_gem.c
2 *
3 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
4 * Author: Inki Dae <inki.dae@samsung.com>
5 *
Inki Daed81aecb2012-12-18 02:30:17 +09006 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
Inki Dae1c248b72011-10-04 19:19:01 +090010 */
11
David Howells760285e2012-10-02 18:01:07 +010012#include <drm/drmP.h>
David Herrmann0de23972013-07-24 21:07:52 +020013#include <drm/drm_vma_manager.h>
Inki Dae1c248b72011-10-04 19:19:01 +090014
Inki Dae2b358922012-03-16 18:47:05 +090015#include <linux/shmem_fs.h>
Joonyoung Shim01ed50d2015-08-16 14:33:08 +090016#include <linux/dma-buf.h>
Dan Williams01c8f1c2016-01-15 16:56:40 -080017#include <linux/pfn_t.h>
Inki Dae1c248b72011-10-04 19:19:01 +090018#include <drm/exynos_drm.h>
19
20#include "exynos_drm_drv.h"
21#include "exynos_drm_gem.h"
Vikas Sajjan3fec4532013-08-23 12:05:06 +053022#include "exynos_drm_iommu.h"
Inki Dae1c248b72011-10-04 19:19:01 +090023
Joonyoung Shim813fd67b2015-10-02 09:33:47 +090024static int exynos_drm_alloc_buf(struct exynos_drm_gem *exynos_gem)
Joonyoung Shim2a8cb482015-08-16 14:38:49 +090025{
Joonyoung Shim813fd67b2015-10-02 09:33:47 +090026 struct drm_device *dev = exynos_gem->base.dev;
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -070027 unsigned long attr;
Joonyoung Shim2a8cb482015-08-16 14:38:49 +090028 unsigned int nr_pages;
Marek Szyprowskidf547bf72015-10-13 13:47:20 +020029 struct sg_table sgt;
30 int ret = -ENOMEM;
Joonyoung Shim2a8cb482015-08-16 14:38:49 +090031
Joonyoung Shim813fd67b2015-10-02 09:33:47 +090032 if (exynos_gem->dma_addr) {
Joonyoung Shim2a8cb482015-08-16 14:38:49 +090033 DRM_DEBUG_KMS("already allocated.\n");
34 return 0;
35 }
36
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -070037 exynos_gem->dma_attrs = 0;
Joonyoung Shim2a8cb482015-08-16 14:38:49 +090038
39 /*
40 * if EXYNOS_BO_CONTIG, fully physically contiguous memory
41 * region will be allocated else physically contiguous
42 * as possible.
43 */
Joonyoung Shim813fd67b2015-10-02 09:33:47 +090044 if (!(exynos_gem->flags & EXYNOS_BO_NONCONTIG))
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -070045 exynos_gem->dma_attrs |= DMA_ATTR_FORCE_CONTIGUOUS;
Joonyoung Shim2a8cb482015-08-16 14:38:49 +090046
47 /*
48 * if EXYNOS_BO_WC or EXYNOS_BO_NONCACHABLE, writecombine mapping
49 * else cachable mapping.
50 */
Joonyoung Shim813fd67b2015-10-02 09:33:47 +090051 if (exynos_gem->flags & EXYNOS_BO_WC ||
52 !(exynos_gem->flags & EXYNOS_BO_CACHABLE))
Joonyoung Shim2a8cb482015-08-16 14:38:49 +090053 attr = DMA_ATTR_WRITE_COMBINE;
54 else
55 attr = DMA_ATTR_NON_CONSISTENT;
56
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -070057 exynos_gem->dma_attrs |= attr;
58 exynos_gem->dma_attrs |= DMA_ATTR_NO_KERNEL_MAPPING;
Joonyoung Shim2a8cb482015-08-16 14:38:49 +090059
Joonyoung Shim813fd67b2015-10-02 09:33:47 +090060 nr_pages = exynos_gem->size >> PAGE_SHIFT;
Joonyoung Shim2a8cb482015-08-16 14:38:49 +090061
Michal Hocko20981052017-05-17 14:23:12 +020062 exynos_gem->pages = kvmalloc_array(nr_pages, sizeof(struct page *),
63 GFP_KERNEL | __GFP_ZERO);
Marek Szyprowskidf547bf72015-10-13 13:47:20 +020064 if (!exynos_gem->pages) {
65 DRM_ERROR("failed to allocate pages.\n");
66 return -ENOMEM;
Joonyoung Shim333e8e52015-09-16 14:29:34 +090067 }
Joonyoung Shim2a8cb482015-08-16 14:38:49 +090068
Marek Szyprowskif43c3592016-02-29 17:50:53 +090069 exynos_gem->cookie = dma_alloc_attrs(to_dma_dev(dev), exynos_gem->size,
Joonyoung Shim813fd67b2015-10-02 09:33:47 +090070 &exynos_gem->dma_addr, GFP_KERNEL,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -070071 exynos_gem->dma_attrs);
Joonyoung Shim813fd67b2015-10-02 09:33:47 +090072 if (!exynos_gem->cookie) {
Joonyoung Shim333e8e52015-09-16 14:29:34 +090073 DRM_ERROR("failed to allocate buffer.\n");
Marek Szyprowskidf547bf72015-10-13 13:47:20 +020074 goto err_free;
Joonyoung Shim333e8e52015-09-16 14:29:34 +090075 }
76
Marek Szyprowskif43c3592016-02-29 17:50:53 +090077 ret = dma_get_sgtable_attrs(to_dma_dev(dev), &sgt, exynos_gem->cookie,
Marek Szyprowskidf547bf72015-10-13 13:47:20 +020078 exynos_gem->dma_addr, exynos_gem->size,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -070079 exynos_gem->dma_attrs);
Marek Szyprowskidf547bf72015-10-13 13:47:20 +020080 if (ret < 0) {
81 DRM_ERROR("failed to get sgtable.\n");
82 goto err_dma_free;
Joonyoung Shim2a8cb482015-08-16 14:38:49 +090083 }
84
Marek Szyprowskidf547bf72015-10-13 13:47:20 +020085 if (drm_prime_sg_to_page_addr_arrays(&sgt, exynos_gem->pages, NULL,
86 nr_pages)) {
87 DRM_ERROR("invalid sgtable.\n");
88 ret = -EINVAL;
89 goto err_sgt_free;
90 }
91
92 sg_free_table(&sgt);
93
Joonyoung Shim2a8cb482015-08-16 14:38:49 +090094 DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n",
Joonyoung Shim813fd67b2015-10-02 09:33:47 +090095 (unsigned long)exynos_gem->dma_addr, exynos_gem->size);
Joonyoung Shim2a8cb482015-08-16 14:38:49 +090096
97 return 0;
Marek Szyprowskidf547bf72015-10-13 13:47:20 +020098
99err_sgt_free:
100 sg_free_table(&sgt);
101err_dma_free:
Marek Szyprowskif43c3592016-02-29 17:50:53 +0900102 dma_free_attrs(to_dma_dev(dev), exynos_gem->size, exynos_gem->cookie,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -0700103 exynos_gem->dma_addr, exynos_gem->dma_attrs);
Marek Szyprowskidf547bf72015-10-13 13:47:20 +0200104err_free:
Michal Hocko20981052017-05-17 14:23:12 +0200105 kvfree(exynos_gem->pages);
Marek Szyprowskidf547bf72015-10-13 13:47:20 +0200106
107 return ret;
Joonyoung Shim2a8cb482015-08-16 14:38:49 +0900108}
109
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900110static void exynos_drm_free_buf(struct exynos_drm_gem *exynos_gem)
Joonyoung Shim2a8cb482015-08-16 14:38:49 +0900111{
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900112 struct drm_device *dev = exynos_gem->base.dev;
Joonyoung Shim2a8cb482015-08-16 14:38:49 +0900113
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900114 if (!exynos_gem->dma_addr) {
Joonyoung Shim2a8cb482015-08-16 14:38:49 +0900115 DRM_DEBUG_KMS("dma_addr is invalid.\n");
116 return;
117 }
118
119 DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n",
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900120 (unsigned long)exynos_gem->dma_addr, exynos_gem->size);
Joonyoung Shim2a8cb482015-08-16 14:38:49 +0900121
Marek Szyprowskif43c3592016-02-29 17:50:53 +0900122 dma_free_attrs(to_dma_dev(dev), exynos_gem->size, exynos_gem->cookie,
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900123 (dma_addr_t)exynos_gem->dma_addr,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -0700124 exynos_gem->dma_attrs);
Joonyoung Shim333e8e52015-09-16 14:29:34 +0900125
Michal Hocko20981052017-05-17 14:23:12 +0200126 kvfree(exynos_gem->pages);
Joonyoung Shim2a8cb482015-08-16 14:38:49 +0900127}
128
Joonyoung Shim23648392011-12-13 14:39:13 +0900129static int exynos_drm_gem_handle_create(struct drm_gem_object *obj,
130 struct drm_file *file_priv,
131 unsigned int *handle)
Inki Dae1c248b72011-10-04 19:19:01 +0900132{
Inki Dae1c248b72011-10-04 19:19:01 +0900133 int ret;
134
Inki Dae1c248b72011-10-04 19:19:01 +0900135 /*
136 * allocate a id of idr table where the obj is registered
137 * and handle has the id what user can see.
138 */
139 ret = drm_gem_handle_create(file_priv, obj, handle);
140 if (ret)
Joonyoung Shim23648392011-12-13 14:39:13 +0900141 return ret;
Inki Dae1c248b72011-10-04 19:19:01 +0900142
143 DRM_DEBUG_KMS("gem handle = 0x%x\n", *handle);
144
145 /* drop reference from allocate - handle holds it now. */
146 drm_gem_object_unreference_unlocked(obj);
147
Joonyoung Shim23648392011-12-13 14:39:13 +0900148 return 0;
149}
Inki Dae1c248b72011-10-04 19:19:01 +0900150
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900151void exynos_drm_gem_destroy(struct exynos_drm_gem *exynos_gem)
Joonyoung Shim23648392011-12-13 14:39:13 +0900152{
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900153 struct drm_gem_object *obj = &exynos_gem->base;
Joonyoung Shim23648392011-12-13 14:39:13 +0900154
Daniel Vettera8e11d12013-08-15 00:02:37 +0200155 DRM_DEBUG_KMS("handle count = %d\n", obj->handle_count);
Joonyoung Shim23648392011-12-13 14:39:13 +0900156
Inki Daec374e732012-06-12 16:52:54 +0900157 /*
158 * do not release memory region from exporter.
159 *
160 * the region will be released by exporter
161 * once dmabuf's refcount becomes 0.
162 */
163 if (obj->import_attach)
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900164 drm_prime_gem_destroy(obj, exynos_gem->sgt);
Joonyoung Shim7c935372015-09-16 14:14:54 +0900165 else
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900166 exynos_drm_free_buf(exynos_gem);
Inki Daec374e732012-06-12 16:52:54 +0900167
Joonyoung Shim23648392011-12-13 14:39:13 +0900168 /* release file pointer to gem object. */
Inki Dae1c248b72011-10-04 19:19:01 +0900169 drm_gem_object_release(obj);
170
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900171 kfree(exynos_gem);
Joonyoung Shim23648392011-12-13 14:39:13 +0900172}
173
Inki Daea4f19aa2013-03-11 21:15:59 +0900174unsigned long exynos_drm_gem_get_size(struct drm_device *dev,
175 unsigned int gem_handle,
176 struct drm_file *file_priv)
177{
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900178 struct exynos_drm_gem *exynos_gem;
Inki Daea4f19aa2013-03-11 21:15:59 +0900179 struct drm_gem_object *obj;
180
Chris Wilsona8ad0bd2016-05-09 11:04:54 +0100181 obj = drm_gem_object_lookup(file_priv, gem_handle);
Inki Daea4f19aa2013-03-11 21:15:59 +0900182 if (!obj) {
183 DRM_ERROR("failed to lookup gem object.\n");
184 return 0;
185 }
186
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900187 exynos_gem = to_exynos_gem(obj);
Inki Daea4f19aa2013-03-11 21:15:59 +0900188
189 drm_gem_object_unreference_unlocked(obj);
190
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900191 return exynos_gem->size;
Inki Daea4f19aa2013-03-11 21:15:59 +0900192}
193
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900194static struct exynos_drm_gem *exynos_drm_gem_init(struct drm_device *dev,
195 unsigned long size)
Joonyoung Shim23648392011-12-13 14:39:13 +0900196{
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900197 struct exynos_drm_gem *exynos_gem;
Joonyoung Shim23648392011-12-13 14:39:13 +0900198 struct drm_gem_object *obj;
199 int ret;
200
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900201 exynos_gem = kzalloc(sizeof(*exynos_gem), GFP_KERNEL);
202 if (!exynos_gem)
Joonyoung Shim5f3f4262015-07-28 17:53:22 +0900203 return ERR_PTR(-ENOMEM);
Joonyoung Shim23648392011-12-13 14:39:13 +0900204
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900205 exynos_gem->size = size;
206 obj = &exynos_gem->base;
Joonyoung Shim23648392011-12-13 14:39:13 +0900207
208 ret = drm_gem_object_init(dev, obj, size);
209 if (ret < 0) {
210 DRM_ERROR("failed to initialize gem object\n");
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900211 kfree(exynos_gem);
Joonyoung Shim5f3f4262015-07-28 17:53:22 +0900212 return ERR_PTR(ret);
Joonyoung Shim23648392011-12-13 14:39:13 +0900213 }
214
Joonyoung Shim48cf53f2015-07-28 17:53:23 +0900215 ret = drm_gem_create_mmap_offset(obj);
216 if (ret < 0) {
217 drm_gem_object_release(obj);
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900218 kfree(exynos_gem);
Joonyoung Shim48cf53f2015-07-28 17:53:23 +0900219 return ERR_PTR(ret);
220 }
221
Krzysztof Kozlowski9cdf0ed2017-03-14 20:38:04 +0200222 DRM_DEBUG_KMS("created file object = %pK\n", obj->filp);
Joonyoung Shim23648392011-12-13 14:39:13 +0900223
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900224 return exynos_gem;
Inki Dae1c248b72011-10-04 19:19:01 +0900225}
226
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900227struct exynos_drm_gem *exynos_drm_gem_create(struct drm_device *dev,
228 unsigned int flags,
229 unsigned long size)
Inki Daef088d5a2011-11-12 14:51:23 +0900230{
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900231 struct exynos_drm_gem *exynos_gem;
Inki Dae2b358922012-03-16 18:47:05 +0900232 int ret;
Inki Daef088d5a2011-11-12 14:51:23 +0900233
Joonyoung Shimc4130bc2015-08-16 14:15:06 +0900234 if (flags & ~(EXYNOS_BO_MASK)) {
Shuah Khan63eb0a122016-08-10 11:30:36 -0600235 DRM_ERROR("invalid GEM buffer flags: %u\n", flags);
Joonyoung Shimc4130bc2015-08-16 14:15:06 +0900236 return ERR_PTR(-EINVAL);
237 }
238
Inki Daedcf9af82012-04-03 21:27:58 +0900239 if (!size) {
Shuah Khan63eb0a122016-08-10 11:30:36 -0600240 DRM_ERROR("invalid GEM buffer size: %lu\n", size);
Inki Daedcf9af82012-04-03 21:27:58 +0900241 return ERR_PTR(-EINVAL);
242 }
Inki Daef088d5a2011-11-12 14:51:23 +0900243
Joonyoung Shimeb57da82015-07-28 17:53:27 +0900244 size = roundup(size, PAGE_SIZE);
Inki Daedcf9af82012-04-03 21:27:58 +0900245
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900246 exynos_gem = exynos_drm_gem_init(dev, size);
247 if (IS_ERR(exynos_gem))
248 return exynos_gem;
Inki Dae2b358922012-03-16 18:47:05 +0900249
250 /* set memory type and cache attribute from user side. */
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900251 exynos_gem->flags = flags;
Inki Dae2b358922012-03-16 18:47:05 +0900252
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900253 ret = exynos_drm_alloc_buf(exynos_gem);
Joonyoung Shim2a8cb482015-08-16 14:38:49 +0900254 if (ret < 0) {
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900255 drm_gem_object_release(&exynos_gem->base);
256 kfree(exynos_gem);
Joonyoung Shim2a8cb482015-08-16 14:38:49 +0900257 return ERR_PTR(ret);
258 }
Inki Daef088d5a2011-11-12 14:51:23 +0900259
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900260 return exynos_gem;
Inki Daef088d5a2011-11-12 14:51:23 +0900261}
262
Inki Dae1c248b72011-10-04 19:19:01 +0900263int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data,
Joonyoung Shimee5e7702011-12-13 14:20:23 +0900264 struct drm_file *file_priv)
Inki Dae1c248b72011-10-04 19:19:01 +0900265{
266 struct drm_exynos_gem_create *args = data;
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900267 struct exynos_drm_gem *exynos_gem;
Joonyoung Shim23648392011-12-13 14:39:13 +0900268 int ret;
Inki Dae1c248b72011-10-04 19:19:01 +0900269
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900270 exynos_gem = exynos_drm_gem_create(dev, args->flags, args->size);
271 if (IS_ERR(exynos_gem))
272 return PTR_ERR(exynos_gem);
Inki Dae1c248b72011-10-04 19:19:01 +0900273
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900274 ret = exynos_drm_gem_handle_create(&exynos_gem->base, file_priv,
275 &args->handle);
Joonyoung Shim23648392011-12-13 14:39:13 +0900276 if (ret) {
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900277 exynos_drm_gem_destroy(exynos_gem);
Joonyoung Shim23648392011-12-13 14:39:13 +0900278 return ret;
279 }
280
Inki Dae1c248b72011-10-04 19:19:01 +0900281 return 0;
282}
283
Joonyoung Shim6564c652016-03-08 14:12:59 +0900284int exynos_drm_gem_map_ioctl(struct drm_device *dev, void *data,
285 struct drm_file *file_priv)
286{
287 struct drm_exynos_gem_map *args = data;
288
Noralf Trønnes4d12c2332017-08-06 17:41:02 +0200289 return drm_gem_dumb_map_offset(file_priv, dev, args->handle,
290 &args->offset);
Joonyoung Shim6564c652016-03-08 14:12:59 +0900291}
292
Inki Daed87342c2012-11-03 21:53:24 -0700293dma_addr_t *exynos_drm_gem_get_dma_addr(struct drm_device *dev,
Inki Daef0b1bda2012-03-16 18:47:06 +0900294 unsigned int gem_handle,
Inki Daed87342c2012-11-03 21:53:24 -0700295 struct drm_file *filp)
Inki Daef0b1bda2012-03-16 18:47:06 +0900296{
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900297 struct exynos_drm_gem *exynos_gem;
Inki Daef0b1bda2012-03-16 18:47:06 +0900298 struct drm_gem_object *obj;
299
Chris Wilsona8ad0bd2016-05-09 11:04:54 +0100300 obj = drm_gem_object_lookup(filp, gem_handle);
Inki Daef0b1bda2012-03-16 18:47:06 +0900301 if (!obj) {
302 DRM_ERROR("failed to lookup gem object.\n");
303 return ERR_PTR(-EINVAL);
304 }
305
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900306 exynos_gem = to_exynos_gem(obj);
Inki Daef0b1bda2012-03-16 18:47:06 +0900307
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900308 return &exynos_gem->dma_addr;
Inki Daef0b1bda2012-03-16 18:47:06 +0900309}
310
311void exynos_drm_gem_put_dma_addr(struct drm_device *dev,
312 unsigned int gem_handle,
Inki Daed87342c2012-11-03 21:53:24 -0700313 struct drm_file *filp)
Inki Daef0b1bda2012-03-16 18:47:06 +0900314{
Inki Daef0b1bda2012-03-16 18:47:06 +0900315 struct drm_gem_object *obj;
316
Chris Wilsona8ad0bd2016-05-09 11:04:54 +0100317 obj = drm_gem_object_lookup(filp, gem_handle);
Inki Daef0b1bda2012-03-16 18:47:06 +0900318 if (!obj) {
319 DRM_ERROR("failed to lookup gem object.\n");
320 return;
321 }
322
Inki Daef0b1bda2012-03-16 18:47:06 +0900323 drm_gem_object_unreference_unlocked(obj);
324
325 /*
326 * decrease obj->refcount one more time because we has already
327 * increased it at exynos_drm_gem_get_dma_addr().
328 */
329 drm_gem_object_unreference_unlocked(obj);
330}
331
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900332static int exynos_drm_gem_mmap_buffer(struct exynos_drm_gem *exynos_gem,
Joonyoung Shimee5e7702011-12-13 14:20:23 +0900333 struct vm_area_struct *vma)
Inki Dae1c248b72011-10-04 19:19:01 +0900334{
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900335 struct drm_device *drm_dev = exynos_gem->base.dev;
Inki Dae0519f9a2012-10-20 07:53:42 -0700336 unsigned long vm_size;
Inki Dae5b07c662012-11-08 21:52:54 +0900337 int ret;
Inki Dae1c248b72011-10-04 19:19:01 +0900338
Inki Dae832316c2014-09-18 14:19:01 +0900339 vma->vm_flags &= ~VM_PFNMAP;
340 vma->vm_pgoff = 0;
Inki Dae1c248b72011-10-04 19:19:01 +0900341
Inki Dae0519f9a2012-10-20 07:53:42 -0700342 vm_size = vma->vm_end - vma->vm_start;
Inki Dae2b358922012-03-16 18:47:05 +0900343
Inki Dae1c248b72011-10-04 19:19:01 +0900344 /* check if user-requested size is valid. */
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900345 if (vm_size > exynos_gem->size)
Inki Dae1c248b72011-10-04 19:19:01 +0900346 return -EINVAL;
347
Marek Szyprowskif43c3592016-02-29 17:50:53 +0900348 ret = dma_mmap_attrs(to_dma_dev(drm_dev), vma, exynos_gem->cookie,
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900349 exynos_gem->dma_addr, exynos_gem->size,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -0700350 exynos_gem->dma_attrs);
Inki Dae5b07c662012-11-08 21:52:54 +0900351 if (ret < 0) {
352 DRM_ERROR("failed to mmap.\n");
353 return ret;
354 }
355
Inki Dae1c248b72011-10-04 19:19:01 +0900356 return 0;
357}
358
Inki Dae40cd7e02012-05-04 15:51:17 +0900359int exynos_drm_gem_get_ioctl(struct drm_device *dev, void *data,
360 struct drm_file *file_priv)
Joonyoung Shimb4cfd4d2015-09-16 14:29:35 +0900361{
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900362 struct exynos_drm_gem *exynos_gem;
Inki Dae40cd7e02012-05-04 15:51:17 +0900363 struct drm_exynos_gem_info *args = data;
364 struct drm_gem_object *obj;
365
Chris Wilsona8ad0bd2016-05-09 11:04:54 +0100366 obj = drm_gem_object_lookup(file_priv, args->handle);
Inki Dae40cd7e02012-05-04 15:51:17 +0900367 if (!obj) {
368 DRM_ERROR("failed to lookup gem object.\n");
Inki Dae40cd7e02012-05-04 15:51:17 +0900369 return -EINVAL;
370 }
371
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900372 exynos_gem = to_exynos_gem(obj);
Inki Dae40cd7e02012-05-04 15:51:17 +0900373
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900374 args->flags = exynos_gem->flags;
375 args->size = exynos_gem->size;
Inki Dae40cd7e02012-05-04 15:51:17 +0900376
Daniel Vetter6c991a22016-03-30 11:40:47 +0200377 drm_gem_object_unreference_unlocked(obj);
Inki Dae40cd7e02012-05-04 15:51:17 +0900378
379 return 0;
380}
381
Joonyoung Shimee5e7702011-12-13 14:20:23 +0900382void exynos_drm_gem_free_object(struct drm_gem_object *obj)
Inki Dae1c248b72011-10-04 19:19:01 +0900383{
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900384 exynos_drm_gem_destroy(to_exynos_gem(obj));
Inki Dae1c248b72011-10-04 19:19:01 +0900385}
386
387int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
Joonyoung Shimee5e7702011-12-13 14:20:23 +0900388 struct drm_device *dev,
389 struct drm_mode_create_dumb *args)
Inki Dae1c248b72011-10-04 19:19:01 +0900390{
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900391 struct exynos_drm_gem *exynos_gem;
Joonyoung Shim333e8e52015-09-16 14:29:34 +0900392 unsigned int flags;
Joonyoung Shim23648392011-12-13 14:39:13 +0900393 int ret;
Inki Dae1c248b72011-10-04 19:19:01 +0900394
Inki Dae1c248b72011-10-04 19:19:01 +0900395 /*
Masanari Iidac6b78bc2013-10-24 16:02:57 +0900396 * allocate memory to be used for framebuffer.
Inki Dae1c248b72011-10-04 19:19:01 +0900397 * - this callback would be called by user application
398 * with DRM_IOCTL_MODE_CREATE_DUMB command.
399 */
400
Cooper Yuan3fd6b692012-06-29 11:49:45 +0900401 args->pitch = args->width * ((args->bpp + 7) / 8);
Inki Dae7da59072012-08-17 15:24:03 +0900402 args->size = args->pitch * args->height;
Inki Dae1c248b72011-10-04 19:19:01 +0900403
Joonyoung Shim333e8e52015-09-16 14:29:34 +0900404 if (is_drm_iommu_supported(dev))
405 flags = EXYNOS_BO_NONCONTIG | EXYNOS_BO_WC;
406 else
407 flags = EXYNOS_BO_CONTIG | EXYNOS_BO_WC;
Vikas Sajjan3fec4532013-08-23 12:05:06 +0530408
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900409 exynos_gem = exynos_drm_gem_create(dev, flags, args->size);
410 if (IS_ERR(exynos_gem)) {
Rahul Sharma122beea2014-05-07 17:21:29 +0530411 dev_warn(dev->dev, "FB allocation failed.\n");
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900412 return PTR_ERR(exynos_gem);
Rahul Sharma122beea2014-05-07 17:21:29 +0530413 }
Inki Dae1c248b72011-10-04 19:19:01 +0900414
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900415 ret = exynos_drm_gem_handle_create(&exynos_gem->base, file_priv,
416 &args->handle);
Joonyoung Shim23648392011-12-13 14:39:13 +0900417 if (ret) {
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900418 exynos_drm_gem_destroy(exynos_gem);
Joonyoung Shim23648392011-12-13 14:39:13 +0900419 return ret;
420 }
421
Inki Dae1c248b72011-10-04 19:19:01 +0900422 return 0;
423}
424
Dave Jiang11bac802017-02-24 14:56:41 -0800425int exynos_drm_gem_fault(struct vm_fault *vmf)
Inki Dae1c248b72011-10-04 19:19:01 +0900426{
Dave Jiang11bac802017-02-24 14:56:41 -0800427 struct vm_area_struct *vma = vmf->vma;
Inki Dae1c248b72011-10-04 19:19:01 +0900428 struct drm_gem_object *obj = vma->vm_private_data;
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900429 struct exynos_drm_gem *exynos_gem = to_exynos_gem(obj);
Joonyoung Shim0e9a2ee2015-07-28 17:53:19 +0900430 unsigned long pfn;
Inki Dae1c248b72011-10-04 19:19:01 +0900431 pgoff_t page_offset;
432 int ret;
433
Jan Kara1a29d852016-12-14 15:07:01 -0800434 page_offset = (vmf->address - vma->vm_start) >> PAGE_SHIFT;
Inki Dae1c248b72011-10-04 19:19:01 +0900435
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900436 if (page_offset >= (exynos_gem->size >> PAGE_SHIFT)) {
Joonyoung Shim0e9a2ee2015-07-28 17:53:19 +0900437 DRM_ERROR("invalid page offset\n");
438 ret = -EINVAL;
439 goto out;
440 }
Inki Dae1c248b72011-10-04 19:19:01 +0900441
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900442 pfn = page_to_pfn(exynos_gem->pages[page_offset]);
Jan Kara1a29d852016-12-14 15:07:01 -0800443 ret = vm_insert_mixed(vma, vmf->address, __pfn_to_pfn_t(pfn, PFN_DEV));
Joonyoung Shim0e9a2ee2015-07-28 17:53:19 +0900444
445out:
Joonyoung Shim23597e22015-07-28 17:53:17 +0900446 switch (ret) {
447 case 0:
448 case -ERESTARTSYS:
449 case -EINTR:
450 return VM_FAULT_NOPAGE;
451 case -ENOMEM:
452 return VM_FAULT_OOM;
453 default:
454 return VM_FAULT_SIGBUS;
455 }
Inki Dae1c248b72011-10-04 19:19:01 +0900456}
457
Joonyoung Shim5a0202f2016-04-22 16:30:47 +0900458static int exynos_drm_gem_mmap_obj(struct drm_gem_object *obj,
459 struct vm_area_struct *vma)
Inki Dae1c248b72011-10-04 19:19:01 +0900460{
Joonyoung Shim5a0202f2016-04-22 16:30:47 +0900461 struct exynos_drm_gem *exynos_gem = to_exynos_gem(obj);
Inki Dae1c248b72011-10-04 19:19:01 +0900462 int ret;
463
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900464 DRM_DEBUG_KMS("flags = 0x%x\n", exynos_gem->flags);
Joonyoung Shim211b8872015-08-16 14:16:49 +0900465
466 /* non-cachable as default. */
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900467 if (exynos_gem->flags & EXYNOS_BO_CACHABLE)
Joonyoung Shim211b8872015-08-16 14:16:49 +0900468 vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900469 else if (exynos_gem->flags & EXYNOS_BO_WC)
Joonyoung Shim211b8872015-08-16 14:16:49 +0900470 vma->vm_page_prot =
471 pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
472 else
473 vma->vm_page_prot =
474 pgprot_noncached(vm_get_page_prot(vma->vm_flags));
Inki Daec01d73fa2012-04-23 19:26:34 +0900475
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900476 ret = exynos_drm_gem_mmap_buffer(exynos_gem, vma);
Inki Dae832316c2014-09-18 14:19:01 +0900477 if (ret)
478 goto err_close_vm;
479
480 return ret;
481
482err_close_vm:
483 drm_gem_vm_close(vma);
Inki Dae832316c2014-09-18 14:19:01 +0900484
Inki Dae1c248b72011-10-04 19:19:01 +0900485 return ret;
486}
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900487
Joonyoung Shim5a0202f2016-04-22 16:30:47 +0900488int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
489{
490 struct drm_gem_object *obj;
491 int ret;
492
493 /* set vm_area_struct. */
494 ret = drm_gem_mmap(filp, vma);
495 if (ret < 0) {
496 DRM_ERROR("failed to mmap.\n");
497 return ret;
498 }
499
500 obj = vma->vm_private_data;
501
Joonyoung Shim55b19fc2016-04-22 16:30:48 +0900502 if (obj->import_attach)
503 return dma_buf_mmap(obj->dma_buf, vma, 0);
504
Joonyoung Shim5a0202f2016-04-22 16:30:47 +0900505 return exynos_drm_gem_mmap_obj(obj, vma);
506}
507
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900508/* low-level interface prime helpers */
509struct sg_table *exynos_drm_gem_prime_get_sg_table(struct drm_gem_object *obj)
510{
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900511 struct exynos_drm_gem *exynos_gem = to_exynos_gem(obj);
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900512 int npages;
513
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900514 npages = exynos_gem->size >> PAGE_SHIFT;
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900515
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900516 return drm_prime_pages_to_sg(exynos_gem->pages, npages);
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900517}
518
519struct drm_gem_object *
520exynos_drm_gem_prime_import_sg_table(struct drm_device *dev,
521 struct dma_buf_attachment *attach,
522 struct sg_table *sgt)
523{
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900524 struct exynos_drm_gem *exynos_gem;
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900525 int npages;
526 int ret;
527
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900528 exynos_gem = exynos_drm_gem_init(dev, attach->dmabuf->size);
529 if (IS_ERR(exynos_gem)) {
530 ret = PTR_ERR(exynos_gem);
Inki Dae50002d42015-08-31 01:11:53 +0900531 return ERR_PTR(ret);
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900532 }
533
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900534 exynos_gem->dma_addr = sg_dma_address(sgt->sgl);
Joonyoung Shim2a8cb482015-08-16 14:38:49 +0900535
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900536 npages = exynos_gem->size >> PAGE_SHIFT;
Michal Hocko20981052017-05-17 14:23:12 +0200537 exynos_gem->pages = kvmalloc_array(npages, sizeof(struct page *), GFP_KERNEL);
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900538 if (!exynos_gem->pages) {
Joonyoung Shim2a8cb482015-08-16 14:38:49 +0900539 ret = -ENOMEM;
540 goto err;
541 }
542
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900543 ret = drm_prime_sg_to_page_addr_arrays(sgt, exynos_gem->pages, NULL,
544 npages);
Joonyoung Shim2a8cb482015-08-16 14:38:49 +0900545 if (ret < 0)
546 goto err_free_large;
547
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900548 exynos_gem->sgt = sgt;
Joonyoung Shim7c935372015-09-16 14:14:54 +0900549
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900550 if (sgt->nents == 1) {
551 /* always physically continuous memory if sgt->nents is 1. */
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900552 exynos_gem->flags |= EXYNOS_BO_CONTIG;
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900553 } else {
554 /*
555 * this case could be CONTIG or NONCONTIG type but for now
556 * sets NONCONTIG.
557 * TODO. we have to find a way that exporter can notify
558 * the type of its own buffer to importer.
559 */
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900560 exynos_gem->flags |= EXYNOS_BO_NONCONTIG;
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900561 }
562
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900563 return &exynos_gem->base;
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900564
565err_free_large:
Michal Hocko20981052017-05-17 14:23:12 +0200566 kvfree(exynos_gem->pages);
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900567err:
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900568 drm_gem_object_release(&exynos_gem->base);
569 kfree(exynos_gem);
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900570 return ERR_PTR(ret);
571}
572
573void *exynos_drm_gem_prime_vmap(struct drm_gem_object *obj)
574{
575 return NULL;
576}
577
578void exynos_drm_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
579{
580 /* Nothing to do */
581}
Joonyoung Shim5a0202f2016-04-22 16:30:47 +0900582
583int exynos_drm_gem_prime_mmap(struct drm_gem_object *obj,
584 struct vm_area_struct *vma)
585{
586 int ret;
587
588 ret = drm_gem_mmap_obj(obj, obj->size, vma);
589 if (ret < 0)
590 return ret;
591
592 return exynos_drm_gem_mmap_obj(obj, vma);
593}