xref: /netbsd-src/sys/external/bsd/drm2/dist/drm/i915/gem/selftests/i915_gem_dmabuf.c (revision 41ec02673d281bbb3d38e6c78504ce6e30c228c1)
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