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