110be98a7SChris Wilson /*
210be98a7SChris Wilson  * SPDX-License-Identifier: MIT
310be98a7SChris Wilson  *
410be98a7SChris Wilson  * Copyright © 2016 Intel Corporation
510be98a7SChris Wilson  */
610be98a7SChris Wilson 
737d63f8fSChris Wilson #include "i915_drv.h"
810be98a7SChris Wilson #include "i915_selftest.h"
9*6427ab57SMatthew Auld #include "gem/i915_gem_context.h"
1010be98a7SChris Wilson 
11*6427ab57SMatthew Auld #include "mock_context.h"
1210be98a7SChris Wilson #include "mock_dmabuf.h"
13*6427ab57SMatthew Auld #include "igt_gem_utils.h"
14*6427ab57SMatthew Auld #include "selftests/mock_drm.h"
1510be98a7SChris Wilson #include "selftests/mock_gem_device.h"
1610be98a7SChris Wilson 
igt_dmabuf_export(void * arg)1710be98a7SChris Wilson static int igt_dmabuf_export(void *arg)
1810be98a7SChris Wilson {
1910be98a7SChris Wilson 	struct drm_i915_private *i915 = arg;
2010be98a7SChris Wilson 	struct drm_i915_gem_object *obj;
2110be98a7SChris Wilson 	struct dma_buf *dmabuf;
2210be98a7SChris Wilson 
2310be98a7SChris Wilson 	obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
2410be98a7SChris Wilson 	if (IS_ERR(obj))
2510be98a7SChris Wilson 		return PTR_ERR(obj);
2610be98a7SChris Wilson 
27d8080976SDaniel Vetter 	dmabuf = i915_gem_prime_export(&obj->base, 0);
2810be98a7SChris Wilson 	i915_gem_object_put(obj);
2910be98a7SChris Wilson 	if (IS_ERR(dmabuf)) {
3010be98a7SChris Wilson 		pr_err("i915_gem_prime_export failed with err=%d\n",
3110be98a7SChris Wilson 		       (int)PTR_ERR(dmabuf));
3210be98a7SChris Wilson 		return PTR_ERR(dmabuf);
3310be98a7SChris Wilson 	}
3410be98a7SChris Wilson 
3510be98a7SChris Wilson 	dma_buf_put(dmabuf);
3610be98a7SChris Wilson 	return 0;
3710be98a7SChris Wilson }
3810be98a7SChris Wilson 
igt_dmabuf_import_self(void * arg)3910be98a7SChris Wilson static int igt_dmabuf_import_self(void *arg)
4010be98a7SChris Wilson {
4110be98a7SChris Wilson 	struct drm_i915_private *i915 = arg;
42d7b2cb38SThomas Hellström 	struct drm_i915_gem_object *obj, *import_obj;
4310be98a7SChris Wilson 	struct drm_gem_object *import;
4410be98a7SChris Wilson 	struct dma_buf *dmabuf;
4510be98a7SChris Wilson 	int err;
4610be98a7SChris Wilson 
4710be98a7SChris Wilson 	obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
4810be98a7SChris Wilson 	if (IS_ERR(obj))
4910be98a7SChris Wilson 		return PTR_ERR(obj);
5010be98a7SChris Wilson 
51d8080976SDaniel Vetter 	dmabuf = i915_gem_prime_export(&obj->base, 0);
5210be98a7SChris Wilson 	if (IS_ERR(dmabuf)) {
5310be98a7SChris Wilson 		pr_err("i915_gem_prime_export failed with err=%d\n",
5410be98a7SChris Wilson 		       (int)PTR_ERR(dmabuf));
5510be98a7SChris Wilson 		err = PTR_ERR(dmabuf);
5610be98a7SChris Wilson 		goto out;
5710be98a7SChris Wilson 	}
5810be98a7SChris Wilson 
5910be98a7SChris Wilson 	import = i915_gem_prime_import(&i915->drm, dmabuf);
6010be98a7SChris Wilson 	if (IS_ERR(import)) {
6110be98a7SChris Wilson 		pr_err("i915_gem_prime_import failed with err=%d\n",
6210be98a7SChris Wilson 		       (int)PTR_ERR(import));
6310be98a7SChris Wilson 		err = PTR_ERR(import);
6410be98a7SChris Wilson 		goto out_dmabuf;
6510be98a7SChris Wilson 	}
664796054bSNathan Chancellor 	import_obj = to_intel_bo(import);
6710be98a7SChris Wilson 
6810be98a7SChris Wilson 	if (import != &obj->base) {
6910be98a7SChris Wilson 		pr_err("i915_gem_prime_import created a new object!\n");
7010be98a7SChris Wilson 		err = -EINVAL;
7110be98a7SChris Wilson 		goto out_import;
7210be98a7SChris Wilson 	}
73d7b2cb38SThomas Hellström 
74d7b2cb38SThomas Hellström 	i915_gem_object_lock(import_obj, NULL);
75d7b2cb38SThomas Hellström 	err = __i915_gem_object_get_pages(import_obj);
76d7b2cb38SThomas Hellström 	i915_gem_object_unlock(import_obj);
77d7b2cb38SThomas Hellström 	if (err) {
78d7b2cb38SThomas Hellström 		pr_err("Same object dma-buf get_pages failed!\n");
79d7b2cb38SThomas Hellström 		goto out_import;
80d7b2cb38SThomas Hellström 	}
8110be98a7SChris Wilson 
8210be98a7SChris Wilson 	err = 0;
8310be98a7SChris Wilson out_import:
84d7b2cb38SThomas Hellström 	i915_gem_object_put(import_obj);
8510be98a7SChris Wilson out_dmabuf:
8610be98a7SChris Wilson 	dma_buf_put(dmabuf);
8710be98a7SChris Wilson out:
8810be98a7SChris Wilson 	i915_gem_object_put(obj);
8910be98a7SChris Wilson 	return err;
9010be98a7SChris Wilson }
9110be98a7SChris Wilson 
igt_dmabuf_import_same_driver_lmem(void * arg)92cdb35d1eSThomas Hellström static int igt_dmabuf_import_same_driver_lmem(void *arg)
93d7b2cb38SThomas Hellström {
94d7b2cb38SThomas Hellström 	struct drm_i915_private *i915 = arg;
95fa732088SAndi Shyti 	struct intel_memory_region *lmem = i915->mm.regions[INTEL_REGION_LMEM_0];
96cdb35d1eSThomas Hellström 	struct drm_i915_gem_object *obj;
97cdb35d1eSThomas Hellström 	struct drm_gem_object *import;
98cdb35d1eSThomas Hellström 	struct dma_buf *dmabuf;
99cdb35d1eSThomas Hellström 	int err;
100cdb35d1eSThomas Hellström 
101cdb35d1eSThomas Hellström 	if (!lmem)
102cdb35d1eSThomas Hellström 		return 0;
103cdb35d1eSThomas Hellström 
104cdb35d1eSThomas Hellström 	force_different_devices = true;
105cdb35d1eSThomas Hellström 
106cdb35d1eSThomas Hellström 	obj = __i915_gem_object_create_user(i915, PAGE_SIZE, &lmem, 1);
107cdb35d1eSThomas Hellström 	if (IS_ERR(obj)) {
108cdb35d1eSThomas Hellström 		pr_err("__i915_gem_object_create_user failed with err=%ld\n",
109fc7bf4c0SKai Song 		       PTR_ERR(obj));
110cdb35d1eSThomas Hellström 		err = PTR_ERR(obj);
111cdb35d1eSThomas Hellström 		goto out_ret;
112cdb35d1eSThomas Hellström 	}
113cdb35d1eSThomas Hellström 
114cdb35d1eSThomas Hellström 	dmabuf = i915_gem_prime_export(&obj->base, 0);
115cdb35d1eSThomas Hellström 	if (IS_ERR(dmabuf)) {
116cdb35d1eSThomas Hellström 		pr_err("i915_gem_prime_export failed with err=%ld\n",
117cdb35d1eSThomas Hellström 		       PTR_ERR(dmabuf));
118cdb35d1eSThomas Hellström 		err = PTR_ERR(dmabuf);
119cdb35d1eSThomas Hellström 		goto out;
120cdb35d1eSThomas Hellström 	}
121cdb35d1eSThomas Hellström 
122cdb35d1eSThomas Hellström 	/*
123cdb35d1eSThomas Hellström 	 * We expect an import of an LMEM-only object to fail with
124cdb35d1eSThomas Hellström 	 * -EOPNOTSUPP because it can't be migrated to SMEM.
125cdb35d1eSThomas Hellström 	 */
126cdb35d1eSThomas Hellström 	import = i915_gem_prime_import(&i915->drm, dmabuf);
127cdb35d1eSThomas Hellström 	if (!IS_ERR(import)) {
128cdb35d1eSThomas Hellström 		drm_gem_object_put(import);
129cdb35d1eSThomas Hellström 		pr_err("i915_gem_prime_import succeeded when it shouldn't have\n");
130cdb35d1eSThomas Hellström 		err = -EINVAL;
131cdb35d1eSThomas Hellström 	} else if (PTR_ERR(import) != -EOPNOTSUPP) {
132cdb35d1eSThomas Hellström 		pr_err("i915_gem_prime_import failed with the wrong err=%ld\n",
133cdb35d1eSThomas Hellström 		       PTR_ERR(import));
134cdb35d1eSThomas Hellström 		err = PTR_ERR(import);
13546f20a35SNathan Chancellor 	} else {
13646f20a35SNathan Chancellor 		err = 0;
137cdb35d1eSThomas Hellström 	}
138cdb35d1eSThomas Hellström 
139cdb35d1eSThomas Hellström 	dma_buf_put(dmabuf);
140cdb35d1eSThomas Hellström out:
141cdb35d1eSThomas Hellström 	i915_gem_object_put(obj);
142cdb35d1eSThomas Hellström out_ret:
143cdb35d1eSThomas Hellström 	force_different_devices = false;
144cdb35d1eSThomas Hellström 	return err;
145cdb35d1eSThomas Hellström }
146cdb35d1eSThomas Hellström 
verify_access(struct drm_i915_private * i915,struct drm_i915_gem_object * native_obj,struct drm_i915_gem_object * import_obj)147*6427ab57SMatthew Auld static int verify_access(struct drm_i915_private *i915,
148*6427ab57SMatthew Auld 			 struct drm_i915_gem_object *native_obj,
149*6427ab57SMatthew Auld 			 struct drm_i915_gem_object *import_obj)
150*6427ab57SMatthew Auld {
151*6427ab57SMatthew Auld 	struct i915_gem_engines_iter it;
152*6427ab57SMatthew Auld 	struct i915_gem_context *ctx;
153*6427ab57SMatthew Auld 	struct intel_context *ce;
154*6427ab57SMatthew Auld 	struct i915_vma *vma;
155*6427ab57SMatthew Auld 	struct file *file;
156*6427ab57SMatthew Auld 	u32 *vaddr;
157*6427ab57SMatthew Auld 	int err = 0, i;
158*6427ab57SMatthew Auld 
159*6427ab57SMatthew Auld 	file = mock_file(i915);
160*6427ab57SMatthew Auld 	if (IS_ERR(file))
161*6427ab57SMatthew Auld 		return PTR_ERR(file);
162*6427ab57SMatthew Auld 
163*6427ab57SMatthew Auld 	ctx = live_context(i915, file);
164*6427ab57SMatthew Auld 	if (IS_ERR(ctx)) {
165*6427ab57SMatthew Auld 		err = PTR_ERR(ctx);
166*6427ab57SMatthew Auld 		goto out_file;
167*6427ab57SMatthew Auld 	}
168*6427ab57SMatthew Auld 
169*6427ab57SMatthew Auld 	for_each_gem_engine(ce, i915_gem_context_lock_engines(ctx), it) {
170*6427ab57SMatthew Auld 		if (intel_engine_can_store_dword(ce->engine))
171*6427ab57SMatthew Auld 			break;
172*6427ab57SMatthew Auld 	}
173*6427ab57SMatthew Auld 	i915_gem_context_unlock_engines(ctx);
174*6427ab57SMatthew Auld 	if (!ce)
175*6427ab57SMatthew Auld 		goto out_file;
176*6427ab57SMatthew Auld 
177*6427ab57SMatthew Auld 	vma = i915_vma_instance(import_obj, ce->vm, NULL);
178*6427ab57SMatthew Auld 	if (IS_ERR(vma)) {
179*6427ab57SMatthew Auld 		err = PTR_ERR(vma);
180*6427ab57SMatthew Auld 		goto out_file;
181*6427ab57SMatthew Auld 	}
182*6427ab57SMatthew Auld 
183*6427ab57SMatthew Auld 	err = i915_vma_pin(vma, 0, 0, PIN_USER);
184*6427ab57SMatthew Auld 	if (err)
185*6427ab57SMatthew Auld 		goto out_file;
186*6427ab57SMatthew Auld 
187*6427ab57SMatthew Auld 	err = igt_gpu_fill_dw(ce, vma, 0,
188*6427ab57SMatthew Auld 			      vma->size >> PAGE_SHIFT, 0xdeadbeaf);
189*6427ab57SMatthew Auld 	i915_vma_unpin(vma);
190*6427ab57SMatthew Auld 	if (err)
191*6427ab57SMatthew Auld 		goto out_file;
192*6427ab57SMatthew Auld 
193*6427ab57SMatthew Auld 	err = i915_gem_object_wait(import_obj, 0, MAX_SCHEDULE_TIMEOUT);
194*6427ab57SMatthew Auld 	if (err)
195*6427ab57SMatthew Auld 		goto out_file;
196*6427ab57SMatthew Auld 
197*6427ab57SMatthew Auld 	vaddr = i915_gem_object_pin_map_unlocked(native_obj, I915_MAP_WB);
198*6427ab57SMatthew Auld 	if (IS_ERR(vaddr)) {
199*6427ab57SMatthew Auld 		err = PTR_ERR(vaddr);
200*6427ab57SMatthew Auld 		goto out_file;
201*6427ab57SMatthew Auld 	}
202*6427ab57SMatthew Auld 
203*6427ab57SMatthew Auld 	for (i = 0; i < native_obj->base.size / sizeof(u32); i += PAGE_SIZE / sizeof(u32)) {
204*6427ab57SMatthew Auld 		if (vaddr[i] != 0xdeadbeaf) {
205*6427ab57SMatthew Auld 			pr_err("Data mismatch [%d]=%u\n", i, vaddr[i]);
206*6427ab57SMatthew Auld 			err = -EINVAL;
207*6427ab57SMatthew Auld 			goto out_file;
208*6427ab57SMatthew Auld 		}
209*6427ab57SMatthew Auld 	}
210*6427ab57SMatthew Auld 
211*6427ab57SMatthew Auld out_file:
212*6427ab57SMatthew Auld 	fput(file);
213*6427ab57SMatthew Auld 	return err;
214*6427ab57SMatthew Auld }
215*6427ab57SMatthew Auld 
igt_dmabuf_import_same_driver(struct drm_i915_private * i915,struct intel_memory_region ** regions,unsigned int num_regions)216cdb35d1eSThomas Hellström static int igt_dmabuf_import_same_driver(struct drm_i915_private *i915,
217cdb35d1eSThomas Hellström 					 struct intel_memory_region **regions,
218cdb35d1eSThomas Hellström 					 unsigned int num_regions)
219cdb35d1eSThomas Hellström {
220d7b2cb38SThomas Hellström 	struct drm_i915_gem_object *obj, *import_obj;
221d7b2cb38SThomas Hellström 	struct drm_gem_object *import;
222d7b2cb38SThomas Hellström 	struct dma_buf *dmabuf;
223d7b2cb38SThomas Hellström 	struct dma_buf_attachment *import_attach;
224d7b2cb38SThomas Hellström 	struct sg_table *st;
225d7b2cb38SThomas Hellström 	long timeout;
226d7b2cb38SThomas Hellström 	int err;
227d7b2cb38SThomas Hellström 
228d7b2cb38SThomas Hellström 	force_different_devices = true;
229cdb35d1eSThomas Hellström 
230*6427ab57SMatthew Auld 	obj = __i915_gem_object_create_user(i915, SZ_8M,
231cdb35d1eSThomas Hellström 					    regions, num_regions);
232d7b2cb38SThomas Hellström 	if (IS_ERR(obj)) {
233cdb35d1eSThomas Hellström 		pr_err("__i915_gem_object_create_user failed with err=%ld\n",
234fc7bf4c0SKai Song 		       PTR_ERR(obj));
235d7b2cb38SThomas Hellström 		err = PTR_ERR(obj);
236d7b2cb38SThomas Hellström 		goto out_ret;
237d7b2cb38SThomas Hellström 	}
238d7b2cb38SThomas Hellström 
239d7b2cb38SThomas Hellström 	dmabuf = i915_gem_prime_export(&obj->base, 0);
240d7b2cb38SThomas Hellström 	if (IS_ERR(dmabuf)) {
241d7b2cb38SThomas Hellström 		pr_err("i915_gem_prime_export failed with err=%ld\n",
242d7b2cb38SThomas Hellström 		       PTR_ERR(dmabuf));
243d7b2cb38SThomas Hellström 		err = PTR_ERR(dmabuf);
244d7b2cb38SThomas Hellström 		goto out;
245d7b2cb38SThomas Hellström 	}
246d7b2cb38SThomas Hellström 
247d7b2cb38SThomas Hellström 	import = i915_gem_prime_import(&i915->drm, dmabuf);
248d7b2cb38SThomas Hellström 	if (IS_ERR(import)) {
249d7b2cb38SThomas Hellström 		pr_err("i915_gem_prime_import failed with err=%ld\n",
250d7b2cb38SThomas Hellström 		       PTR_ERR(import));
251d7b2cb38SThomas Hellström 		err = PTR_ERR(import);
252d7b2cb38SThomas Hellström 		goto out_dmabuf;
253d7b2cb38SThomas Hellström 	}
2544796054bSNathan Chancellor 	import_obj = to_intel_bo(import);
255d7b2cb38SThomas Hellström 
256d7b2cb38SThomas Hellström 	if (import == &obj->base) {
257d7b2cb38SThomas Hellström 		pr_err("i915_gem_prime_import reused gem object!\n");
258d7b2cb38SThomas Hellström 		err = -EINVAL;
259d7b2cb38SThomas Hellström 		goto out_import;
260d7b2cb38SThomas Hellström 	}
261d7b2cb38SThomas Hellström 
262d7b2cb38SThomas Hellström 	i915_gem_object_lock(import_obj, NULL);
263d7b2cb38SThomas Hellström 	err = __i915_gem_object_get_pages(import_obj);
264d7b2cb38SThomas Hellström 	if (err) {
265d7b2cb38SThomas Hellström 		pr_err("Different objects dma-buf get_pages failed!\n");
266d7b2cb38SThomas Hellström 		i915_gem_object_unlock(import_obj);
267d7b2cb38SThomas Hellström 		goto out_import;
268d7b2cb38SThomas Hellström 	}
269d7b2cb38SThomas Hellström 
270d7b2cb38SThomas Hellström 	/*
271d7b2cb38SThomas Hellström 	 * If the exported object is not in system memory, something
272d7b2cb38SThomas Hellström 	 * weird is going on. TODO: When p2p is supported, this is no
273d7b2cb38SThomas Hellström 	 * longer considered weird.
274d7b2cb38SThomas Hellström 	 */
275d7b2cb38SThomas Hellström 	if (obj->mm.region != i915->mm.regions[INTEL_REGION_SMEM]) {
276d7b2cb38SThomas Hellström 		pr_err("Exported dma-buf is not in system memory\n");
277d7b2cb38SThomas Hellström 		err = -EINVAL;
278d7b2cb38SThomas Hellström 	}
279d7b2cb38SThomas Hellström 
280d7b2cb38SThomas Hellström 	i915_gem_object_unlock(import_obj);
281d7b2cb38SThomas Hellström 
282*6427ab57SMatthew Auld 	err = verify_access(i915, obj, import_obj);
283*6427ab57SMatthew Auld 	if (err)
284*6427ab57SMatthew Auld 		goto out_import;
285*6427ab57SMatthew Auld 
286d7b2cb38SThomas Hellström 	/* Now try a fake an importer */
287d7b2cb38SThomas Hellström 	import_attach = dma_buf_attach(dmabuf, obj->base.dev->dev);
288d7b2cb38SThomas Hellström 	if (IS_ERR(import_attach)) {
289d7b2cb38SThomas Hellström 		err = PTR_ERR(import_attach);
290d7b2cb38SThomas Hellström 		goto out_import;
291d7b2cb38SThomas Hellström 	}
292d7b2cb38SThomas Hellström 
293d7b2cb38SThomas Hellström 	st = dma_buf_map_attachment_unlocked(import_attach, DMA_BIDIRECTIONAL);
294d7b2cb38SThomas Hellström 	if (IS_ERR(st)) {
295d7b2cb38SThomas Hellström 		err = PTR_ERR(st);
296d7b2cb38SThomas Hellström 		goto out_detach;
297d7b2cb38SThomas Hellström 	}
298d7b2cb38SThomas Hellström 
2997bc80a54SChristian König 	timeout = dma_resv_wait_timeout(dmabuf->resv, DMA_RESV_USAGE_WRITE,
3007bc80a54SChristian König 					true, 5 * HZ);
301d7b2cb38SThomas Hellström 	if (!timeout) {
302d7b2cb38SThomas Hellström 		pr_err("dmabuf wait for exclusive fence timed out.\n");
303d7b2cb38SThomas Hellström 		timeout = -ETIME;
304d7b2cb38SThomas Hellström 	}
305d7b2cb38SThomas Hellström 	err = timeout > 0 ? 0 : timeout;
306d7b2cb38SThomas Hellström 	dma_buf_unmap_attachment_unlocked(import_attach, st, DMA_BIDIRECTIONAL);
307d7b2cb38SThomas Hellström out_detach:
308d7b2cb38SThomas Hellström 	dma_buf_detach(dmabuf, import_attach);
309d7b2cb38SThomas Hellström out_import:
310d7b2cb38SThomas Hellström 	i915_gem_object_put(import_obj);
311d7b2cb38SThomas Hellström out_dmabuf:
312d7b2cb38SThomas Hellström 	dma_buf_put(dmabuf);
313d7b2cb38SThomas Hellström out:
314d7b2cb38SThomas Hellström 	i915_gem_object_put(obj);
315d7b2cb38SThomas Hellström out_ret:
316d7b2cb38SThomas Hellström 	force_different_devices = false;
317d7b2cb38SThomas Hellström 	return err;
318d7b2cb38SThomas Hellström }
319d7b2cb38SThomas Hellström 
igt_dmabuf_import_same_driver_smem(void * arg)320cdb35d1eSThomas Hellström static int igt_dmabuf_import_same_driver_smem(void *arg)
321cdb35d1eSThomas Hellström {
322cdb35d1eSThomas Hellström 	struct drm_i915_private *i915 = arg;
323cdb35d1eSThomas Hellström 	struct intel_memory_region *smem = i915->mm.regions[INTEL_REGION_SMEM];
324cdb35d1eSThomas Hellström 
325cdb35d1eSThomas Hellström 	return igt_dmabuf_import_same_driver(i915, &smem, 1);
326cdb35d1eSThomas Hellström }
327cdb35d1eSThomas Hellström 
igt_dmabuf_import_same_driver_lmem_smem(void * arg)328cdb35d1eSThomas Hellström static int igt_dmabuf_import_same_driver_lmem_smem(void *arg)
329cdb35d1eSThomas Hellström {
330cdb35d1eSThomas Hellström 	struct drm_i915_private *i915 = arg;
331cdb35d1eSThomas Hellström 	struct intel_memory_region *regions[2];
332cdb35d1eSThomas Hellström 
333fa732088SAndi Shyti 	if (!i915->mm.regions[INTEL_REGION_LMEM_0])
334cdb35d1eSThomas Hellström 		return 0;
335cdb35d1eSThomas Hellström 
336fa732088SAndi Shyti 	regions[0] = i915->mm.regions[INTEL_REGION_LMEM_0];
337cdb35d1eSThomas Hellström 	regions[1] = i915->mm.regions[INTEL_REGION_SMEM];
338cdb35d1eSThomas Hellström 	return igt_dmabuf_import_same_driver(i915, regions, 2);
339cdb35d1eSThomas Hellström }
340cdb35d1eSThomas Hellström 
igt_dmabuf_import(void * arg)34110be98a7SChris Wilson static int igt_dmabuf_import(void *arg)
34210be98a7SChris Wilson {
34310be98a7SChris Wilson 	struct drm_i915_private *i915 = arg;
34410be98a7SChris Wilson 	struct drm_i915_gem_object *obj;
34510be98a7SChris Wilson 	struct dma_buf *dmabuf;
34610be98a7SChris Wilson 	void *obj_map, *dma_map;
3477938f421SLucas De Marchi 	struct iosys_map map;
34810be98a7SChris Wilson 	u32 pattern[] = { 0, 0xaa, 0xcc, 0x55, 0xff };
34910be98a7SChris Wilson 	int err, i;
35010be98a7SChris Wilson 
35110be98a7SChris Wilson 	dmabuf = mock_dmabuf(1);
35210be98a7SChris Wilson 	if (IS_ERR(dmabuf))
35310be98a7SChris Wilson 		return PTR_ERR(dmabuf);
35410be98a7SChris Wilson 
35510be98a7SChris Wilson 	obj = to_intel_bo(i915_gem_prime_import(&i915->drm, dmabuf));
35610be98a7SChris Wilson 	if (IS_ERR(obj)) {
35710be98a7SChris Wilson 		pr_err("i915_gem_prime_import failed with err=%d\n",
35810be98a7SChris Wilson 		       (int)PTR_ERR(obj));
35910be98a7SChris Wilson 		err = PTR_ERR(obj);
36010be98a7SChris Wilson 		goto out_dmabuf;
36110be98a7SChris Wilson 	}
36210be98a7SChris Wilson 
36310be98a7SChris Wilson 	if (obj->base.dev != &i915->drm) {
36410be98a7SChris Wilson 		pr_err("i915_gem_prime_import created a non-i915 object!\n");
36510be98a7SChris Wilson 		err = -EINVAL;
36610be98a7SChris Wilson 		goto out_obj;
36710be98a7SChris Wilson 	}
36810be98a7SChris Wilson 
36910be98a7SChris Wilson 	if (obj->base.size != PAGE_SIZE) {
37010be98a7SChris Wilson 		pr_err("i915_gem_prime_import is wrong size found %lld, expected %ld\n",
37110be98a7SChris Wilson 		       (long long)obj->base.size, PAGE_SIZE);
37210be98a7SChris Wilson 		err = -EINVAL;
37310be98a7SChris Wilson 		goto out_obj;
37410be98a7SChris Wilson 	}
37510be98a7SChris Wilson 
3766619ccf1SThomas Zimmermann 	err = dma_buf_vmap_unlocked(dmabuf, &map);
3776619ccf1SThomas Zimmermann 	dma_map = err ? NULL : map.vaddr;
37810be98a7SChris Wilson 	if (!dma_map) {
37910be98a7SChris Wilson 		pr_err("dma_buf_vmap failed\n");
38010be98a7SChris Wilson 		err = -ENOMEM;
38110be98a7SChris Wilson 		goto out_obj;
38210be98a7SChris Wilson 	}
38310be98a7SChris Wilson 
38410be98a7SChris Wilson 	if (0) { /* Can not yet map dmabuf */
38510be98a7SChris Wilson 		obj_map = i915_gem_object_pin_map(obj, I915_MAP_WB);
38610be98a7SChris Wilson 		if (IS_ERR(obj_map)) {
38710be98a7SChris Wilson 			err = PTR_ERR(obj_map);
38810be98a7SChris Wilson 			pr_err("i915_gem_object_pin_map failed with err=%d\n", err);
38910be98a7SChris Wilson 			goto out_dma_map;
39010be98a7SChris Wilson 		}
39110be98a7SChris Wilson 
39210be98a7SChris Wilson 		for (i = 0; i < ARRAY_SIZE(pattern); i++) {
39310be98a7SChris Wilson 			memset(dma_map, pattern[i], PAGE_SIZE);
39410be98a7SChris Wilson 			if (memchr_inv(obj_map, pattern[i], PAGE_SIZE)) {
39510be98a7SChris Wilson 				err = -EINVAL;
39610be98a7SChris Wilson 				pr_err("imported vmap not all set to %x!\n", pattern[i]);
39710be98a7SChris Wilson 				i915_gem_object_unpin_map(obj);
39810be98a7SChris Wilson 				goto out_dma_map;
39910be98a7SChris Wilson 			}
40010be98a7SChris Wilson 		}
40110be98a7SChris Wilson 
40210be98a7SChris Wilson 		for (i = 0; i < ARRAY_SIZE(pattern); i++) {
40310be98a7SChris Wilson 			memset(obj_map, pattern[i], PAGE_SIZE);
40410be98a7SChris Wilson 			if (memchr_inv(dma_map, pattern[i], PAGE_SIZE)) {
40510be98a7SChris Wilson 				err = -EINVAL;
40610be98a7SChris Wilson 				pr_err("exported vmap not all set to %x!\n", pattern[i]);
40710be98a7SChris Wilson 				i915_gem_object_unpin_map(obj);
40810be98a7SChris Wilson 				goto out_dma_map;
40910be98a7SChris Wilson 			}
41010be98a7SChris Wilson 		}
41110be98a7SChris Wilson 
41210be98a7SChris Wilson 		i915_gem_object_unpin_map(obj);
41310be98a7SChris Wilson 	}
41410be98a7SChris Wilson 
41510be98a7SChris Wilson 	err = 0;
41610be98a7SChris Wilson out_dma_map:
41720e76f1aSThomas Zimmermann 	dma_buf_vunmap_unlocked(dmabuf, &map);
41810be98a7SChris Wilson out_obj:
41910be98a7SChris Wilson 	i915_gem_object_put(obj);
42010be98a7SChris Wilson out_dmabuf:
42110be98a7SChris Wilson 	dma_buf_put(dmabuf);
42210be98a7SChris Wilson 	return err;
42310be98a7SChris Wilson }
42410be98a7SChris Wilson 
igt_dmabuf_import_ownership(void * arg)42510be98a7SChris Wilson static int igt_dmabuf_import_ownership(void *arg)
42610be98a7SChris Wilson {
42710be98a7SChris Wilson 	struct drm_i915_private *i915 = arg;
42810be98a7SChris Wilson 	struct drm_i915_gem_object *obj;
42910be98a7SChris Wilson 	struct dma_buf *dmabuf;
4307938f421SLucas De Marchi 	struct iosys_map map;
43110be98a7SChris Wilson 	void *ptr;
43210be98a7SChris Wilson 	int err;
43310be98a7SChris Wilson 
43410be98a7SChris Wilson 	dmabuf = mock_dmabuf(1);
43510be98a7SChris Wilson 	if (IS_ERR(dmabuf))
43610be98a7SChris Wilson 		return PTR_ERR(dmabuf);
43710be98a7SChris Wilson 
4386619ccf1SThomas Zimmermann 	err = dma_buf_vmap_unlocked(dmabuf, &map);
4396619ccf1SThomas Zimmermann 	ptr = err ? NULL : map.vaddr;
44010be98a7SChris Wilson 	if (!ptr) {
44110be98a7SChris Wilson 		pr_err("dma_buf_vmap failed\n");
44210be98a7SChris Wilson 		err = -ENOMEM;
44310be98a7SChris Wilson 		goto err_dmabuf;
44410be98a7SChris Wilson 	}
44510be98a7SChris Wilson 
44610be98a7SChris Wilson 	memset(ptr, 0xc5, PAGE_SIZE);
44720e76f1aSThomas Zimmermann 	dma_buf_vunmap_unlocked(dmabuf, &map);
44810be98a7SChris Wilson 
44910be98a7SChris Wilson 	obj = to_intel_bo(i915_gem_prime_import(&i915->drm, dmabuf));
45010be98a7SChris Wilson 	if (IS_ERR(obj)) {
45110be98a7SChris Wilson 		pr_err("i915_gem_prime_import failed with err=%d\n",
45210be98a7SChris Wilson 		       (int)PTR_ERR(obj));
45310be98a7SChris Wilson 		err = PTR_ERR(obj);
45410be98a7SChris Wilson 		goto err_dmabuf;
45510be98a7SChris Wilson 	}
45610be98a7SChris Wilson 
45710be98a7SChris Wilson 	dma_buf_put(dmabuf);
45810be98a7SChris Wilson 
459e3729844SMaarten Lankhorst 	err = i915_gem_object_pin_pages_unlocked(obj);
46010be98a7SChris Wilson 	if (err) {
46110be98a7SChris Wilson 		pr_err("i915_gem_object_pin_pages failed with err=%d\n", err);
46210be98a7SChris Wilson 		goto out_obj;
46310be98a7SChris Wilson 	}
46410be98a7SChris Wilson 
46510be98a7SChris Wilson 	err = 0;
46610be98a7SChris Wilson 	i915_gem_object_unpin_pages(obj);
46710be98a7SChris Wilson out_obj:
46810be98a7SChris Wilson 	i915_gem_object_put(obj);
46910be98a7SChris Wilson 	return err;
47010be98a7SChris Wilson 
47110be98a7SChris Wilson err_dmabuf:
47210be98a7SChris Wilson 	dma_buf_put(dmabuf);
47310be98a7SChris Wilson 	return err;
47410be98a7SChris Wilson }
47510be98a7SChris Wilson 
igt_dmabuf_export_vmap(void * arg)47610be98a7SChris Wilson static int igt_dmabuf_export_vmap(void *arg)
47710be98a7SChris Wilson {
47810be98a7SChris Wilson 	struct drm_i915_private *i915 = arg;
47910be98a7SChris Wilson 	struct drm_i915_gem_object *obj;
48010be98a7SChris Wilson 	struct dma_buf *dmabuf;
4817938f421SLucas De Marchi 	struct iosys_map map;
48210be98a7SChris Wilson 	void *ptr;
48310be98a7SChris Wilson 	int err;
48410be98a7SChris Wilson 
48510be98a7SChris Wilson 	obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
48610be98a7SChris Wilson 	if (IS_ERR(obj))
48710be98a7SChris Wilson 		return PTR_ERR(obj);
48810be98a7SChris Wilson 
489d8080976SDaniel Vetter 	dmabuf = i915_gem_prime_export(&obj->base, 0);
49010be98a7SChris Wilson 	if (IS_ERR(dmabuf)) {
49110be98a7SChris Wilson 		pr_err("i915_gem_prime_export failed with err=%d\n",
49210be98a7SChris Wilson 		       (int)PTR_ERR(dmabuf));
49310be98a7SChris Wilson 		err = PTR_ERR(dmabuf);
49410be98a7SChris Wilson 		goto err_obj;
49510be98a7SChris Wilson 	}
49610be98a7SChris Wilson 	i915_gem_object_put(obj);
49710be98a7SChris Wilson 
4986619ccf1SThomas Zimmermann 	err = dma_buf_vmap_unlocked(dmabuf, &map);
4996619ccf1SThomas Zimmermann 	ptr = err ? NULL : map.vaddr;
50010be98a7SChris Wilson 	if (!ptr) {
50110be98a7SChris Wilson 		pr_err("dma_buf_vmap failed\n");
50210be98a7SChris Wilson 		err = -ENOMEM;
50310be98a7SChris Wilson 		goto out;
50410be98a7SChris Wilson 	}
50510be98a7SChris Wilson 
50610be98a7SChris Wilson 	if (memchr_inv(ptr, 0, dmabuf->size)) {
50710be98a7SChris Wilson 		pr_err("Exported object not initialiased to zero!\n");
50810be98a7SChris Wilson 		err = -EINVAL;
50910be98a7SChris Wilson 		goto out;
51010be98a7SChris Wilson 	}
51110be98a7SChris Wilson 
51210be98a7SChris Wilson 	memset(ptr, 0xc5, dmabuf->size);
51310be98a7SChris Wilson 
51410be98a7SChris Wilson 	err = 0;
51520e76f1aSThomas Zimmermann 	dma_buf_vunmap_unlocked(dmabuf, &map);
51610be98a7SChris Wilson out:
51710be98a7SChris Wilson 	dma_buf_put(dmabuf);
51810be98a7SChris Wilson 	return err;
51910be98a7SChris Wilson 
52010be98a7SChris Wilson err_obj:
52110be98a7SChris Wilson 	i915_gem_object_put(obj);
52210be98a7SChris Wilson 	return err;
52310be98a7SChris Wilson }
52410be98a7SChris Wilson 
i915_gem_dmabuf_mock_selftests(void)52510be98a7SChris Wilson int i915_gem_dmabuf_mock_selftests(void)
52610be98a7SChris Wilson {
52710be98a7SChris Wilson 	static const struct i915_subtest tests[] = {
52810be98a7SChris Wilson 		SUBTEST(igt_dmabuf_export),
52910be98a7SChris Wilson 		SUBTEST(igt_dmabuf_import_self),
53010be98a7SChris Wilson 		SUBTEST(igt_dmabuf_import),
53110be98a7SChris Wilson 		SUBTEST(igt_dmabuf_import_ownership),
53210be98a7SChris Wilson 		SUBTEST(igt_dmabuf_export_vmap),
53310be98a7SChris Wilson 	};
53410be98a7SChris Wilson 	struct drm_i915_private *i915;
53510be98a7SChris Wilson 	int err;
53610be98a7SChris Wilson 
53710be98a7SChris Wilson 	i915 = mock_gem_device();
53810be98a7SChris Wilson 	if (!i915)
53910be98a7SChris Wilson 		return -ENOMEM;
54010be98a7SChris Wilson 
54110be98a7SChris Wilson 	err = i915_subtests(tests, i915);
54210be98a7SChris Wilson 
54382be0d75SDaniel Vetter 	mock_destroy_device(i915);
54410be98a7SChris Wilson 	return err;
54510be98a7SChris Wilson }
54610be98a7SChris Wilson 
i915_gem_dmabuf_live_selftests(struct drm_i915_private * i915)54710be98a7SChris Wilson int i915_gem_dmabuf_live_selftests(struct drm_i915_private *i915)
54810be98a7SChris Wilson {
54910be98a7SChris Wilson 	static const struct i915_subtest tests[] = {
55010be98a7SChris Wilson 		SUBTEST(igt_dmabuf_export),
551cdb35d1eSThomas Hellström 		SUBTEST(igt_dmabuf_import_same_driver_lmem),
552cdb35d1eSThomas Hellström 		SUBTEST(igt_dmabuf_import_same_driver_smem),
553cdb35d1eSThomas Hellström 		SUBTEST(igt_dmabuf_import_same_driver_lmem_smem),
55410be98a7SChris Wilson 	};
55510be98a7SChris Wilson 
55661faec5fSMatthew Brost 	return i915_live_subtests(tests, i915);
55710be98a7SChris Wilson }
558