blob: bdf5a7655228b69ad799ffdce859876cf176563c [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. */
Thomas Zimmermannaf7d9102018-06-18 15:17:38 +0200146 drm_gem_object_put_unlocked(obj);
Inki Dae1c248b72011-10-04 19:19:01 +0900147
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
Thomas Zimmermannaf7d9102018-06-18 15:17:38 +0200189 drm_gem_object_put_unlocked(obj);
Inki Daea4f19aa2013-03-11 21:15:59 +0900190
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
Marek Szyprowski120a2642017-11-22 14:14:47 +0100250 if (!is_drm_iommu_supported(dev) && (flags & EXYNOS_BO_NONCONTIG)) {
251 /*
252 * when no IOMMU is available, all allocated buffers are
253 * contiguous anyway, so drop EXYNOS_BO_NONCONTIG flag
254 */
255 flags &= ~EXYNOS_BO_NONCONTIG;
256 DRM_WARN("Non-contiguous allocation is not supported without IOMMU, falling back to contiguous buffer\n");
257 }
258
Inki Dae2b358922012-03-16 18:47:05 +0900259 /* set memory type and cache attribute from user side. */
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900260 exynos_gem->flags = flags;
Inki Dae2b358922012-03-16 18:47:05 +0900261
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900262 ret = exynos_drm_alloc_buf(exynos_gem);
Joonyoung Shim2a8cb482015-08-16 14:38:49 +0900263 if (ret < 0) {
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900264 drm_gem_object_release(&exynos_gem->base);
265 kfree(exynos_gem);
Joonyoung Shim2a8cb482015-08-16 14:38:49 +0900266 return ERR_PTR(ret);
267 }
Inki Daef088d5a2011-11-12 14:51:23 +0900268
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900269 return exynos_gem;
Inki Daef088d5a2011-11-12 14:51:23 +0900270}
271
Inki Dae1c248b72011-10-04 19:19:01 +0900272int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data,
Joonyoung Shimee5e7702011-12-13 14:20:23 +0900273 struct drm_file *file_priv)
Inki Dae1c248b72011-10-04 19:19:01 +0900274{
275 struct drm_exynos_gem_create *args = data;
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900276 struct exynos_drm_gem *exynos_gem;
Joonyoung Shim23648392011-12-13 14:39:13 +0900277 int ret;
Inki Dae1c248b72011-10-04 19:19:01 +0900278
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900279 exynos_gem = exynos_drm_gem_create(dev, args->flags, args->size);
280 if (IS_ERR(exynos_gem))
281 return PTR_ERR(exynos_gem);
Inki Dae1c248b72011-10-04 19:19:01 +0900282
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900283 ret = exynos_drm_gem_handle_create(&exynos_gem->base, file_priv,
284 &args->handle);
Joonyoung Shim23648392011-12-13 14:39:13 +0900285 if (ret) {
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900286 exynos_drm_gem_destroy(exynos_gem);
Joonyoung Shim23648392011-12-13 14:39:13 +0900287 return ret;
288 }
289
Inki Dae1c248b72011-10-04 19:19:01 +0900290 return 0;
291}
292
Joonyoung Shim6564c652016-03-08 14:12:59 +0900293int exynos_drm_gem_map_ioctl(struct drm_device *dev, void *data,
294 struct drm_file *file_priv)
295{
296 struct drm_exynos_gem_map *args = data;
297
Noralf Trønnes4d12c2332017-08-06 17:41:02 +0200298 return drm_gem_dumb_map_offset(file_priv, dev, args->handle,
299 &args->offset);
Joonyoung Shim6564c652016-03-08 14:12:59 +0900300}
301
Inki Daed87342c2012-11-03 21:53:24 -0700302dma_addr_t *exynos_drm_gem_get_dma_addr(struct drm_device *dev,
Inki Daef0b1bda2012-03-16 18:47:06 +0900303 unsigned int gem_handle,
Inki Daed87342c2012-11-03 21:53:24 -0700304 struct drm_file *filp)
Inki Daef0b1bda2012-03-16 18:47:06 +0900305{
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900306 struct exynos_drm_gem *exynos_gem;
Inki Daef0b1bda2012-03-16 18:47:06 +0900307 struct drm_gem_object *obj;
308
Chris Wilsona8ad0bd2016-05-09 11:04:54 +0100309 obj = drm_gem_object_lookup(filp, gem_handle);
Inki Daef0b1bda2012-03-16 18:47:06 +0900310 if (!obj) {
311 DRM_ERROR("failed to lookup gem object.\n");
312 return ERR_PTR(-EINVAL);
313 }
314
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900315 exynos_gem = to_exynos_gem(obj);
Inki Daef0b1bda2012-03-16 18:47:06 +0900316
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900317 return &exynos_gem->dma_addr;
Inki Daef0b1bda2012-03-16 18:47:06 +0900318}
319
320void exynos_drm_gem_put_dma_addr(struct drm_device *dev,
321 unsigned int gem_handle,
Inki Daed87342c2012-11-03 21:53:24 -0700322 struct drm_file *filp)
Inki Daef0b1bda2012-03-16 18:47:06 +0900323{
Inki Daef0b1bda2012-03-16 18:47:06 +0900324 struct drm_gem_object *obj;
325
Chris Wilsona8ad0bd2016-05-09 11:04:54 +0100326 obj = drm_gem_object_lookup(filp, gem_handle);
Inki Daef0b1bda2012-03-16 18:47:06 +0900327 if (!obj) {
328 DRM_ERROR("failed to lookup gem object.\n");
329 return;
330 }
331
Thomas Zimmermannaf7d9102018-06-18 15:17:38 +0200332 drm_gem_object_put_unlocked(obj);
Inki Daef0b1bda2012-03-16 18:47:06 +0900333
334 /*
335 * decrease obj->refcount one more time because we has already
336 * increased it at exynos_drm_gem_get_dma_addr().
337 */
Thomas Zimmermannaf7d9102018-06-18 15:17:38 +0200338 drm_gem_object_put_unlocked(obj);
Inki Daef0b1bda2012-03-16 18:47:06 +0900339}
340
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900341static int exynos_drm_gem_mmap_buffer(struct exynos_drm_gem *exynos_gem,
Joonyoung Shimee5e7702011-12-13 14:20:23 +0900342 struct vm_area_struct *vma)
Inki Dae1c248b72011-10-04 19:19:01 +0900343{
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900344 struct drm_device *drm_dev = exynos_gem->base.dev;
Inki Dae0519f9a2012-10-20 07:53:42 -0700345 unsigned long vm_size;
Inki Dae5b07c662012-11-08 21:52:54 +0900346 int ret;
Inki Dae1c248b72011-10-04 19:19:01 +0900347
Inki Dae832316c2014-09-18 14:19:01 +0900348 vma->vm_flags &= ~VM_PFNMAP;
349 vma->vm_pgoff = 0;
Inki Dae1c248b72011-10-04 19:19:01 +0900350
Inki Dae0519f9a2012-10-20 07:53:42 -0700351 vm_size = vma->vm_end - vma->vm_start;
Inki Dae2b358922012-03-16 18:47:05 +0900352
Inki Dae1c248b72011-10-04 19:19:01 +0900353 /* check if user-requested size is valid. */
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900354 if (vm_size > exynos_gem->size)
Inki Dae1c248b72011-10-04 19:19:01 +0900355 return -EINVAL;
356
Marek Szyprowskif43c3592016-02-29 17:50:53 +0900357 ret = dma_mmap_attrs(to_dma_dev(drm_dev), vma, exynos_gem->cookie,
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900358 exynos_gem->dma_addr, exynos_gem->size,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -0700359 exynos_gem->dma_attrs);
Inki Dae5b07c662012-11-08 21:52:54 +0900360 if (ret < 0) {
361 DRM_ERROR("failed to mmap.\n");
362 return ret;
363 }
364
Inki Dae1c248b72011-10-04 19:19:01 +0900365 return 0;
366}
367
Inki Dae40cd7e02012-05-04 15:51:17 +0900368int exynos_drm_gem_get_ioctl(struct drm_device *dev, void *data,
369 struct drm_file *file_priv)
Joonyoung Shimb4cfd4d2015-09-16 14:29:35 +0900370{
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900371 struct exynos_drm_gem *exynos_gem;
Inki Dae40cd7e02012-05-04 15:51:17 +0900372 struct drm_exynos_gem_info *args = data;
373 struct drm_gem_object *obj;
374
Chris Wilsona8ad0bd2016-05-09 11:04:54 +0100375 obj = drm_gem_object_lookup(file_priv, args->handle);
Inki Dae40cd7e02012-05-04 15:51:17 +0900376 if (!obj) {
377 DRM_ERROR("failed to lookup gem object.\n");
Inki Dae40cd7e02012-05-04 15:51:17 +0900378 return -EINVAL;
379 }
380
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900381 exynos_gem = to_exynos_gem(obj);
Inki Dae40cd7e02012-05-04 15:51:17 +0900382
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900383 args->flags = exynos_gem->flags;
384 args->size = exynos_gem->size;
Inki Dae40cd7e02012-05-04 15:51:17 +0900385
Thomas Zimmermannaf7d9102018-06-18 15:17:38 +0200386 drm_gem_object_put_unlocked(obj);
Inki Dae40cd7e02012-05-04 15:51:17 +0900387
388 return 0;
389}
390
Joonyoung Shimee5e7702011-12-13 14:20:23 +0900391void exynos_drm_gem_free_object(struct drm_gem_object *obj)
Inki Dae1c248b72011-10-04 19:19:01 +0900392{
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900393 exynos_drm_gem_destroy(to_exynos_gem(obj));
Inki Dae1c248b72011-10-04 19:19:01 +0900394}
395
396int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
Joonyoung Shimee5e7702011-12-13 14:20:23 +0900397 struct drm_device *dev,
398 struct drm_mode_create_dumb *args)
Inki Dae1c248b72011-10-04 19:19:01 +0900399{
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900400 struct exynos_drm_gem *exynos_gem;
Joonyoung Shim333e8e52015-09-16 14:29:34 +0900401 unsigned int flags;
Joonyoung Shim23648392011-12-13 14:39:13 +0900402 int ret;
Inki Dae1c248b72011-10-04 19:19:01 +0900403
Inki Dae1c248b72011-10-04 19:19:01 +0900404 /*
Masanari Iidac6b78bc2013-10-24 16:02:57 +0900405 * allocate memory to be used for framebuffer.
Inki Dae1c248b72011-10-04 19:19:01 +0900406 * - this callback would be called by user application
407 * with DRM_IOCTL_MODE_CREATE_DUMB command.
408 */
409
Cooper Yuan3fd6b692012-06-29 11:49:45 +0900410 args->pitch = args->width * ((args->bpp + 7) / 8);
Inki Dae7da59072012-08-17 15:24:03 +0900411 args->size = args->pitch * args->height;
Inki Dae1c248b72011-10-04 19:19:01 +0900412
Joonyoung Shim333e8e52015-09-16 14:29:34 +0900413 if (is_drm_iommu_supported(dev))
414 flags = EXYNOS_BO_NONCONTIG | EXYNOS_BO_WC;
415 else
416 flags = EXYNOS_BO_CONTIG | EXYNOS_BO_WC;
Vikas Sajjan3fec4532013-08-23 12:05:06 +0530417
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900418 exynos_gem = exynos_drm_gem_create(dev, flags, args->size);
419 if (IS_ERR(exynos_gem)) {
Rahul Sharma122beea2014-05-07 17:21:29 +0530420 dev_warn(dev->dev, "FB allocation failed.\n");
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900421 return PTR_ERR(exynos_gem);
Rahul Sharma122beea2014-05-07 17:21:29 +0530422 }
Inki Dae1c248b72011-10-04 19:19:01 +0900423
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900424 ret = exynos_drm_gem_handle_create(&exynos_gem->base, file_priv,
425 &args->handle);
Joonyoung Shim23648392011-12-13 14:39:13 +0900426 if (ret) {
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900427 exynos_drm_gem_destroy(exynos_gem);
Joonyoung Shim23648392011-12-13 14:39:13 +0900428 return ret;
429 }
430
Inki Dae1c248b72011-10-04 19:19:01 +0900431 return 0;
432}
433
Souptick Joarder8a8d9b22018-04-14 21:34:29 +0530434vm_fault_t exynos_drm_gem_fault(struct vm_fault *vmf)
Inki Dae1c248b72011-10-04 19:19:01 +0900435{
Dave Jiang11bac802017-02-24 14:56:41 -0800436 struct vm_area_struct *vma = vmf->vma;
Inki Dae1c248b72011-10-04 19:19:01 +0900437 struct drm_gem_object *obj = vma->vm_private_data;
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900438 struct exynos_drm_gem *exynos_gem = to_exynos_gem(obj);
Joonyoung Shim0e9a2ee2015-07-28 17:53:19 +0900439 unsigned long pfn;
Inki Dae1c248b72011-10-04 19:19:01 +0900440 pgoff_t page_offset;
Inki Dae1c248b72011-10-04 19:19:01 +0900441
Jan Kara1a29d852016-12-14 15:07:01 -0800442 page_offset = (vmf->address - vma->vm_start) >> PAGE_SHIFT;
Inki Dae1c248b72011-10-04 19:19:01 +0900443
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900444 if (page_offset >= (exynos_gem->size >> PAGE_SHIFT)) {
Joonyoung Shim0e9a2ee2015-07-28 17:53:19 +0900445 DRM_ERROR("invalid page offset\n");
Souptick Joarder8a8d9b22018-04-14 21:34:29 +0530446 return VM_FAULT_SIGBUS;
Joonyoung Shim0e9a2ee2015-07-28 17:53:19 +0900447 }
Inki Dae1c248b72011-10-04 19:19:01 +0900448
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900449 pfn = page_to_pfn(exynos_gem->pages[page_offset]);
Souptick Joarder8a8d9b22018-04-14 21:34:29 +0530450 return vmf_insert_mixed(vma, vmf->address,
451 __pfn_to_pfn_t(pfn, PFN_DEV));
Inki Dae1c248b72011-10-04 19:19:01 +0900452}
453
Joonyoung Shim5a0202f2016-04-22 16:30:47 +0900454static int exynos_drm_gem_mmap_obj(struct drm_gem_object *obj,
455 struct vm_area_struct *vma)
Inki Dae1c248b72011-10-04 19:19:01 +0900456{
Joonyoung Shim5a0202f2016-04-22 16:30:47 +0900457 struct exynos_drm_gem *exynos_gem = to_exynos_gem(obj);
Inki Dae1c248b72011-10-04 19:19:01 +0900458 int ret;
459
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900460 DRM_DEBUG_KMS("flags = 0x%x\n", exynos_gem->flags);
Joonyoung Shim211b8872015-08-16 14:16:49 +0900461
462 /* non-cachable as default. */
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900463 if (exynos_gem->flags & EXYNOS_BO_CACHABLE)
Joonyoung Shim211b8872015-08-16 14:16:49 +0900464 vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900465 else if (exynos_gem->flags & EXYNOS_BO_WC)
Joonyoung Shim211b8872015-08-16 14:16:49 +0900466 vma->vm_page_prot =
467 pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
468 else
469 vma->vm_page_prot =
470 pgprot_noncached(vm_get_page_prot(vma->vm_flags));
Inki Daec01d73fa2012-04-23 19:26:34 +0900471
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900472 ret = exynos_drm_gem_mmap_buffer(exynos_gem, vma);
Inki Dae832316c2014-09-18 14:19:01 +0900473 if (ret)
474 goto err_close_vm;
475
476 return ret;
477
478err_close_vm:
479 drm_gem_vm_close(vma);
Inki Dae832316c2014-09-18 14:19:01 +0900480
Inki Dae1c248b72011-10-04 19:19:01 +0900481 return ret;
482}
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900483
Joonyoung Shim5a0202f2016-04-22 16:30:47 +0900484int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
485{
486 struct drm_gem_object *obj;
487 int ret;
488
489 /* set vm_area_struct. */
490 ret = drm_gem_mmap(filp, vma);
491 if (ret < 0) {
492 DRM_ERROR("failed to mmap.\n");
493 return ret;
494 }
495
496 obj = vma->vm_private_data;
497
Joonyoung Shim55b19fc2016-04-22 16:30:48 +0900498 if (obj->import_attach)
499 return dma_buf_mmap(obj->dma_buf, vma, 0);
500
Joonyoung Shim5a0202f2016-04-22 16:30:47 +0900501 return exynos_drm_gem_mmap_obj(obj, vma);
502}
503
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900504/* low-level interface prime helpers */
Marek Szyprowski89452d42017-10-30 08:28:09 +0100505struct drm_gem_object *exynos_drm_gem_prime_import(struct drm_device *dev,
506 struct dma_buf *dma_buf)
507{
508 return drm_gem_prime_import_dev(dev, dma_buf, to_dma_dev(dev));
509}
510
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900511struct sg_table *exynos_drm_gem_prime_get_sg_table(struct drm_gem_object *obj)
512{
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900513 struct exynos_drm_gem *exynos_gem = to_exynos_gem(obj);
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900514 int npages;
515
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900516 npages = exynos_gem->size >> PAGE_SHIFT;
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900517
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900518 return drm_prime_pages_to_sg(exynos_gem->pages, npages);
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900519}
520
521struct drm_gem_object *
522exynos_drm_gem_prime_import_sg_table(struct drm_device *dev,
523 struct dma_buf_attachment *attach,
524 struct sg_table *sgt)
525{
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900526 struct exynos_drm_gem *exynos_gem;
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900527 int npages;
528 int ret;
529
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900530 exynos_gem = exynos_drm_gem_init(dev, attach->dmabuf->size);
531 if (IS_ERR(exynos_gem)) {
532 ret = PTR_ERR(exynos_gem);
Inki Dae50002d42015-08-31 01:11:53 +0900533 return ERR_PTR(ret);
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900534 }
535
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900536 exynos_gem->dma_addr = sg_dma_address(sgt->sgl);
Joonyoung Shim2a8cb482015-08-16 14:38:49 +0900537
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900538 npages = exynos_gem->size >> PAGE_SHIFT;
Michal Hocko20981052017-05-17 14:23:12 +0200539 exynos_gem->pages = kvmalloc_array(npages, sizeof(struct page *), GFP_KERNEL);
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900540 if (!exynos_gem->pages) {
Joonyoung Shim2a8cb482015-08-16 14:38:49 +0900541 ret = -ENOMEM;
542 goto err;
543 }
544
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900545 ret = drm_prime_sg_to_page_addr_arrays(sgt, exynos_gem->pages, NULL,
546 npages);
Joonyoung Shim2a8cb482015-08-16 14:38:49 +0900547 if (ret < 0)
548 goto err_free_large;
549
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900550 exynos_gem->sgt = sgt;
Joonyoung Shim7c935372015-09-16 14:14:54 +0900551
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900552 if (sgt->nents == 1) {
553 /* always physically continuous memory if sgt->nents is 1. */
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900554 exynos_gem->flags |= EXYNOS_BO_CONTIG;
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900555 } else {
556 /*
557 * this case could be CONTIG or NONCONTIG type but for now
558 * sets NONCONTIG.
559 * TODO. we have to find a way that exporter can notify
560 * the type of its own buffer to importer.
561 */
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900562 exynos_gem->flags |= EXYNOS_BO_NONCONTIG;
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900563 }
564
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900565 return &exynos_gem->base;
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900566
567err_free_large:
Michal Hocko20981052017-05-17 14:23:12 +0200568 kvfree(exynos_gem->pages);
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900569err:
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900570 drm_gem_object_release(&exynos_gem->base);
571 kfree(exynos_gem);
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900572 return ERR_PTR(ret);
573}
574
575void *exynos_drm_gem_prime_vmap(struct drm_gem_object *obj)
576{
577 return NULL;
578}
579
580void exynos_drm_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
581{
582 /* Nothing to do */
583}
Joonyoung Shim5a0202f2016-04-22 16:30:47 +0900584
585int exynos_drm_gem_prime_mmap(struct drm_gem_object *obj,
586 struct vm_area_struct *vma)
587{
588 int ret;
589
590 ret = drm_gem_mmap_obj(obj, obj->size, vma);
591 if (ret < 0)
592 return ret;
593
594 return exynos_drm_gem_mmap_obj(obj, vma);
595}