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 	u32 pattern[] = { 0, 0xaa, 0xcc, 0x55, 0xff };
86 	int err, i;
87 
88 	dmabuf = mock_dmabuf(1);
89 	if (IS_ERR(dmabuf))
90 		return PTR_ERR(dmabuf);
91 
92 	obj = to_intel_bo(i915_gem_prime_import(&i915->drm, dmabuf));
93 	if (IS_ERR(obj)) {
94 		pr_err("i915_gem_prime_import failed with err=%d\n",
95 		       (int)PTR_ERR(obj));
96 		err = PTR_ERR(obj);
97 		goto out_dmabuf;
98 	}
99 
100 	if (obj->base.dev != &i915->drm) {
101 		pr_err("i915_gem_prime_import created a non-i915 object!\n");
102 		err = -EINVAL;
103 		goto out_obj;
104 	}
105 
106 	if (obj->base.size != PAGE_SIZE) {
107 		pr_err("i915_gem_prime_import is wrong size found %lld, expected %ld\n",
108 		       (long long)obj->base.size, PAGE_SIZE);
109 		err = -EINVAL;
110 		goto out_obj;
111 	}
112 
113 	dma_map = dma_buf_vmap(dmabuf);
114 	if (!dma_map) {
115 		pr_err("dma_buf_vmap failed\n");
116 		err = -ENOMEM;
117 		goto out_obj;
118 	}
119 
120 	if (0) { /* Can not yet map dmabuf */
121 		obj_map = i915_gem_object_pin_map(obj, I915_MAP_WB);
122 		if (IS_ERR(obj_map)) {
123 			err = PTR_ERR(obj_map);
124 			pr_err("i915_gem_object_pin_map failed with err=%d\n", err);
125 			goto out_dma_map;
126 		}
127 
128 		for (i = 0; i < ARRAY_SIZE(pattern); i++) {
129 			memset(dma_map, pattern[i], PAGE_SIZE);
130 			if (memchr_inv(obj_map, pattern[i], PAGE_SIZE)) {
131 				err = -EINVAL;
132 				pr_err("imported vmap not all set to %x!\n", pattern[i]);
133 				i915_gem_object_unpin_map(obj);
134 				goto out_dma_map;
135 			}
136 		}
137 
138 		for (i = 0; i < ARRAY_SIZE(pattern); i++) {
139 			memset(obj_map, pattern[i], PAGE_SIZE);
140 			if (memchr_inv(dma_map, pattern[i], PAGE_SIZE)) {
141 				err = -EINVAL;
142 				pr_err("exported vmap not all set to %x!\n", pattern[i]);
143 				i915_gem_object_unpin_map(obj);
144 				goto out_dma_map;
145 			}
146 		}
147 
148 		i915_gem_object_unpin_map(obj);
149 	}
150 
151 	err = 0;
152 out_dma_map:
153 	dma_buf_vunmap(dmabuf, dma_map);
154 out_obj:
155 	i915_gem_object_put(obj);
156 out_dmabuf:
157 	dma_buf_put(dmabuf);
158 	return err;
159 }
160 
161 static int igt_dmabuf_import_ownership(void *arg)
162 {
163 	struct drm_i915_private *i915 = arg;
164 	struct drm_i915_gem_object *obj;
165 	struct dma_buf *dmabuf;
166 	void *ptr;
167 	int err;
168 
169 	dmabuf = mock_dmabuf(1);
170 	if (IS_ERR(dmabuf))
171 		return PTR_ERR(dmabuf);
172 
173 	ptr = dma_buf_vmap(dmabuf);
174 	if (!ptr) {
175 		pr_err("dma_buf_vmap failed\n");
176 		err = -ENOMEM;
177 		goto err_dmabuf;
178 	}
179 
180 	memset(ptr, 0xc5, PAGE_SIZE);
181 	dma_buf_vunmap(dmabuf, ptr);
182 
183 	obj = to_intel_bo(i915_gem_prime_import(&i915->drm, dmabuf));
184 	if (IS_ERR(obj)) {
185 		pr_err("i915_gem_prime_import failed with err=%d\n",
186 		       (int)PTR_ERR(obj));
187 		err = PTR_ERR(obj);
188 		goto err_dmabuf;
189 	}
190 
191 	dma_buf_put(dmabuf);
192 
193 	err = i915_gem_object_pin_pages(obj);
194 	if (err) {
195 		pr_err("i915_gem_object_pin_pages failed with err=%d\n", err);
196 		goto out_obj;
197 	}
198 
199 	err = 0;
200 	i915_gem_object_unpin_pages(obj);
201 out_obj:
202 	i915_gem_object_put(obj);
203 	return err;
204 
205 err_dmabuf:
206 	dma_buf_put(dmabuf);
207 	return err;
208 }
209 
210 static int igt_dmabuf_export_vmap(void *arg)
211 {
212 	struct drm_i915_private *i915 = arg;
213 	struct drm_i915_gem_object *obj;
214 	struct dma_buf *dmabuf;
215 	void *ptr;
216 	int err;
217 
218 	obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
219 	if (IS_ERR(obj))
220 		return PTR_ERR(obj);
221 
222 	dmabuf = i915_gem_prime_export(&obj->base, 0);
223 	if (IS_ERR(dmabuf)) {
224 		pr_err("i915_gem_prime_export failed with err=%d\n",
225 		       (int)PTR_ERR(dmabuf));
226 		err = PTR_ERR(dmabuf);
227 		goto err_obj;
228 	}
229 	i915_gem_object_put(obj);
230 
231 	ptr = dma_buf_vmap(dmabuf);
232 	if (!ptr) {
233 		pr_err("dma_buf_vmap failed\n");
234 		err = -ENOMEM;
235 		goto out;
236 	}
237 
238 	if (memchr_inv(ptr, 0, dmabuf->size)) {
239 		pr_err("Exported object not initialiased to zero!\n");
240 		err = -EINVAL;
241 		goto out;
242 	}
243 
244 	memset(ptr, 0xc5, dmabuf->size);
245 
246 	err = 0;
247 	dma_buf_vunmap(dmabuf, ptr);
248 out:
249 	dma_buf_put(dmabuf);
250 	return err;
251 
252 err_obj:
253 	i915_gem_object_put(obj);
254 	return err;
255 }
256 
257 int i915_gem_dmabuf_mock_selftests(void)
258 {
259 	static const struct i915_subtest tests[] = {
260 		SUBTEST(igt_dmabuf_export),
261 		SUBTEST(igt_dmabuf_import_self),
262 		SUBTEST(igt_dmabuf_import),
263 		SUBTEST(igt_dmabuf_import_ownership),
264 		SUBTEST(igt_dmabuf_export_vmap),
265 	};
266 	struct drm_i915_private *i915;
267 	int err;
268 
269 	i915 = mock_gem_device();
270 	if (!i915)
271 		return -ENOMEM;
272 
273 	err = i915_subtests(tests, i915);
274 
275 	drm_dev_put(&i915->drm);
276 	return err;
277 }
278 
279 int i915_gem_dmabuf_live_selftests(struct drm_i915_private *i915)
280 {
281 	static const struct i915_subtest tests[] = {
282 		SUBTEST(igt_dmabuf_export),
283 	};
284 
285 	return i915_subtests(tests, i915);
286 }
287