1 /* $NetBSD: i915_gem_dmabuf.c,v 1.2 2021/12/18 23:45:30 riastradh Exp $ */
2
3 /*
4 * SPDX-License-Identifier: MIT
5 *
6 * Copyright © 2016 Intel Corporation
7 */
8
9 #include <sys/cdefs.h>
10 __KERNEL_RCSID(0, "$NetBSD: i915_gem_dmabuf.c,v 1.2 2021/12/18 23:45:30 riastradh Exp $");
11
12 #include "i915_drv.h"
13 #include "i915_selftest.h"
14
15 #include "mock_dmabuf.h"
16 #include "selftests/mock_gem_device.h"
17
igt_dmabuf_export(void * arg)18 static int igt_dmabuf_export(void *arg)
19 {
20 struct drm_i915_private *i915 = arg;
21 struct drm_i915_gem_object *obj;
22 struct dma_buf *dmabuf;
23
24 obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
25 if (IS_ERR(obj))
26 return PTR_ERR(obj);
27
28 dmabuf = i915_gem_prime_export(&obj->base, 0);
29 i915_gem_object_put(obj);
30 if (IS_ERR(dmabuf)) {
31 pr_err("i915_gem_prime_export failed with err=%d\n",
32 (int)PTR_ERR(dmabuf));
33 return PTR_ERR(dmabuf);
34 }
35
36 dma_buf_put(dmabuf);
37 return 0;
38 }
39
igt_dmabuf_import_self(void * arg)40 static int igt_dmabuf_import_self(void *arg)
41 {
42 struct drm_i915_private *i915 = arg;
43 struct drm_i915_gem_object *obj;
44 struct drm_gem_object *import;
45 struct dma_buf *dmabuf;
46 int err;
47
48 obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
49 if (IS_ERR(obj))
50 return PTR_ERR(obj);
51
52 dmabuf = i915_gem_prime_export(&obj->base, 0);
53 if (IS_ERR(dmabuf)) {
54 pr_err("i915_gem_prime_export failed with err=%d\n",
55 (int)PTR_ERR(dmabuf));
56 err = PTR_ERR(dmabuf);
57 goto out;
58 }
59
60 import = i915_gem_prime_import(&i915->drm, dmabuf);
61 if (IS_ERR(import)) {
62 pr_err("i915_gem_prime_import failed with err=%d\n",
63 (int)PTR_ERR(import));
64 err = PTR_ERR(import);
65 goto out_dmabuf;
66 }
67
68 if (import != &obj->base) {
69 pr_err("i915_gem_prime_import created a new object!\n");
70 err = -EINVAL;
71 goto out_import;
72 }
73
74 err = 0;
75 out_import:
76 i915_gem_object_put(to_intel_bo(import));
77 out_dmabuf:
78 dma_buf_put(dmabuf);
79 out:
80 i915_gem_object_put(obj);
81 return err;
82 }
83
igt_dmabuf_import(void * arg)84 static int igt_dmabuf_import(void *arg)
85 {
86 struct drm_i915_private *i915 = arg;
87 struct drm_i915_gem_object *obj;
88 struct dma_buf *dmabuf;
89 void *obj_map, *dma_map;
90 u32 pattern[] = { 0, 0xaa, 0xcc, 0x55, 0xff };
91 int err, i;
92
93 dmabuf = mock_dmabuf(1);
94 if (IS_ERR(dmabuf))
95 return PTR_ERR(dmabuf);
96
97 obj = to_intel_bo(i915_gem_prime_import(&i915->drm, dmabuf));
98 if (IS_ERR(obj)) {
99 pr_err("i915_gem_prime_import failed with err=%d\n",
100 (int)PTR_ERR(obj));
101 err = PTR_ERR(obj);
102 goto out_dmabuf;
103 }
104
105 if (obj->base.dev != &i915->drm) {
106 pr_err("i915_gem_prime_import created a non-i915 object!\n");
107 err = -EINVAL;
108 goto out_obj;
109 }
110
111 if (obj->base.size != PAGE_SIZE) {
112 pr_err("i915_gem_prime_import is wrong size found %lld, expected %ld\n",
113 (long long)obj->base.size, PAGE_SIZE);
114 err = -EINVAL;
115 goto out_obj;
116 }
117
118 dma_map = dma_buf_vmap(dmabuf);
119 if (!dma_map) {
120 pr_err("dma_buf_vmap failed\n");
121 err = -ENOMEM;
122 goto out_obj;
123 }
124
125 if (0) { /* Can not yet map dmabuf */
126 obj_map = i915_gem_object_pin_map(obj, I915_MAP_WB);
127 if (IS_ERR(obj_map)) {
128 err = PTR_ERR(obj_map);
129 pr_err("i915_gem_object_pin_map failed with err=%d\n", err);
130 goto out_dma_map;
131 }
132
133 for (i = 0; i < ARRAY_SIZE(pattern); i++) {
134 memset(dma_map, pattern[i], PAGE_SIZE);
135 if (memchr_inv(obj_map, pattern[i], PAGE_SIZE)) {
136 err = -EINVAL;
137 pr_err("imported vmap not all set to %x!\n", pattern[i]);
138 i915_gem_object_unpin_map(obj);
139 goto out_dma_map;
140 }
141 }
142
143 for (i = 0; i < ARRAY_SIZE(pattern); i++) {
144 memset(obj_map, pattern[i], PAGE_SIZE);
145 if (memchr_inv(dma_map, pattern[i], PAGE_SIZE)) {
146 err = -EINVAL;
147 pr_err("exported vmap not all set to %x!\n", pattern[i]);
148 i915_gem_object_unpin_map(obj);
149 goto out_dma_map;
150 }
151 }
152
153 i915_gem_object_unpin_map(obj);
154 }
155
156 err = 0;
157 out_dma_map:
158 dma_buf_vunmap(dmabuf, dma_map);
159 out_obj:
160 i915_gem_object_put(obj);
161 out_dmabuf:
162 dma_buf_put(dmabuf);
163 return err;
164 }
165
igt_dmabuf_import_ownership(void * arg)166 static int igt_dmabuf_import_ownership(void *arg)
167 {
168 struct drm_i915_private *i915 = arg;
169 struct drm_i915_gem_object *obj;
170 struct dma_buf *dmabuf;
171 void *ptr;
172 int err;
173
174 dmabuf = mock_dmabuf(1);
175 if (IS_ERR(dmabuf))
176 return PTR_ERR(dmabuf);
177
178 ptr = dma_buf_vmap(dmabuf);
179 if (!ptr) {
180 pr_err("dma_buf_vmap failed\n");
181 err = -ENOMEM;
182 goto err_dmabuf;
183 }
184
185 memset(ptr, 0xc5, PAGE_SIZE);
186 dma_buf_vunmap(dmabuf, ptr);
187
188 obj = to_intel_bo(i915_gem_prime_import(&i915->drm, dmabuf));
189 if (IS_ERR(obj)) {
190 pr_err("i915_gem_prime_import failed with err=%d\n",
191 (int)PTR_ERR(obj));
192 err = PTR_ERR(obj);
193 goto err_dmabuf;
194 }
195
196 dma_buf_put(dmabuf);
197
198 err = i915_gem_object_pin_pages(obj);
199 if (err) {
200 pr_err("i915_gem_object_pin_pages failed with err=%d\n", err);
201 goto out_obj;
202 }
203
204 err = 0;
205 i915_gem_object_unpin_pages(obj);
206 out_obj:
207 i915_gem_object_put(obj);
208 return err;
209
210 err_dmabuf:
211 dma_buf_put(dmabuf);
212 return err;
213 }
214
igt_dmabuf_export_vmap(void * arg)215 static int igt_dmabuf_export_vmap(void *arg)
216 {
217 struct drm_i915_private *i915 = arg;
218 struct drm_i915_gem_object *obj;
219 struct dma_buf *dmabuf;
220 void *ptr;
221 int err;
222
223 obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
224 if (IS_ERR(obj))
225 return PTR_ERR(obj);
226
227 dmabuf = i915_gem_prime_export(&obj->base, 0);
228 if (IS_ERR(dmabuf)) {
229 pr_err("i915_gem_prime_export failed with err=%d\n",
230 (int)PTR_ERR(dmabuf));
231 err = PTR_ERR(dmabuf);
232 goto err_obj;
233 }
234 i915_gem_object_put(obj);
235
236 ptr = dma_buf_vmap(dmabuf);
237 if (!ptr) {
238 pr_err("dma_buf_vmap failed\n");
239 err = -ENOMEM;
240 goto out;
241 }
242
243 if (memchr_inv(ptr, 0, dmabuf->size)) {
244 pr_err("Exported object not initialiased to zero!\n");
245 err = -EINVAL;
246 goto out;
247 }
248
249 memset(ptr, 0xc5, dmabuf->size);
250
251 err = 0;
252 dma_buf_vunmap(dmabuf, ptr);
253 out:
254 dma_buf_put(dmabuf);
255 return err;
256
257 err_obj:
258 i915_gem_object_put(obj);
259 return err;
260 }
261
i915_gem_dmabuf_mock_selftests(void)262 int i915_gem_dmabuf_mock_selftests(void)
263 {
264 static const struct i915_subtest tests[] = {
265 SUBTEST(igt_dmabuf_export),
266 SUBTEST(igt_dmabuf_import_self),
267 SUBTEST(igt_dmabuf_import),
268 SUBTEST(igt_dmabuf_import_ownership),
269 SUBTEST(igt_dmabuf_export_vmap),
270 };
271 struct drm_i915_private *i915;
272 int err;
273
274 i915 = mock_gem_device();
275 if (!i915)
276 return -ENOMEM;
277
278 err = i915_subtests(tests, i915);
279
280 drm_dev_put(&i915->drm);
281 return err;
282 }
283
i915_gem_dmabuf_live_selftests(struct drm_i915_private * i915)284 int i915_gem_dmabuf_live_selftests(struct drm_i915_private *i915)
285 {
286 static const struct i915_subtest tests[] = {
287 SUBTEST(igt_dmabuf_export),
288 };
289
290 return i915_subtests(tests, i915);
291 }
292