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" 910be98a7SChris Wilson 1010be98a7SChris Wilson #include "mock_dmabuf.h" 1110be98a7SChris Wilson #include "selftests/mock_gem_device.h" 1210be98a7SChris Wilson 1310be98a7SChris Wilson static int igt_dmabuf_export(void *arg) 1410be98a7SChris Wilson { 1510be98a7SChris Wilson struct drm_i915_private *i915 = arg; 1610be98a7SChris Wilson struct drm_i915_gem_object *obj; 1710be98a7SChris Wilson struct dma_buf *dmabuf; 1810be98a7SChris Wilson 1910be98a7SChris Wilson obj = i915_gem_object_create_shmem(i915, PAGE_SIZE); 2010be98a7SChris Wilson if (IS_ERR(obj)) 2110be98a7SChris Wilson return PTR_ERR(obj); 2210be98a7SChris Wilson 23d8080976SDaniel Vetter dmabuf = i915_gem_prime_export(&obj->base, 0); 2410be98a7SChris Wilson i915_gem_object_put(obj); 2510be98a7SChris Wilson if (IS_ERR(dmabuf)) { 2610be98a7SChris Wilson pr_err("i915_gem_prime_export failed with err=%d\n", 2710be98a7SChris Wilson (int)PTR_ERR(dmabuf)); 2810be98a7SChris Wilson return PTR_ERR(dmabuf); 2910be98a7SChris Wilson } 3010be98a7SChris Wilson 3110be98a7SChris Wilson dma_buf_put(dmabuf); 3210be98a7SChris Wilson return 0; 3310be98a7SChris Wilson } 3410be98a7SChris Wilson 3510be98a7SChris Wilson static int igt_dmabuf_import_self(void *arg) 3610be98a7SChris Wilson { 3710be98a7SChris Wilson struct drm_i915_private *i915 = arg; 3810be98a7SChris Wilson struct drm_i915_gem_object *obj; 3910be98a7SChris Wilson struct drm_gem_object *import; 4010be98a7SChris Wilson struct dma_buf *dmabuf; 4110be98a7SChris Wilson int err; 4210be98a7SChris Wilson 4310be98a7SChris Wilson obj = i915_gem_object_create_shmem(i915, PAGE_SIZE); 4410be98a7SChris Wilson if (IS_ERR(obj)) 4510be98a7SChris Wilson return PTR_ERR(obj); 4610be98a7SChris Wilson 47d8080976SDaniel Vetter dmabuf = i915_gem_prime_export(&obj->base, 0); 4810be98a7SChris Wilson if (IS_ERR(dmabuf)) { 4910be98a7SChris Wilson pr_err("i915_gem_prime_export failed with err=%d\n", 5010be98a7SChris Wilson (int)PTR_ERR(dmabuf)); 5110be98a7SChris Wilson err = PTR_ERR(dmabuf); 5210be98a7SChris Wilson goto out; 5310be98a7SChris Wilson } 5410be98a7SChris Wilson 5510be98a7SChris Wilson import = i915_gem_prime_import(&i915->drm, dmabuf); 5610be98a7SChris Wilson if (IS_ERR(import)) { 5710be98a7SChris Wilson pr_err("i915_gem_prime_import failed with err=%d\n", 5810be98a7SChris Wilson (int)PTR_ERR(import)); 5910be98a7SChris Wilson err = PTR_ERR(import); 6010be98a7SChris Wilson goto out_dmabuf; 6110be98a7SChris Wilson } 6210be98a7SChris Wilson 6310be98a7SChris Wilson if (import != &obj->base) { 6410be98a7SChris Wilson pr_err("i915_gem_prime_import created a new object!\n"); 6510be98a7SChris Wilson err = -EINVAL; 6610be98a7SChris Wilson goto out_import; 6710be98a7SChris Wilson } 6810be98a7SChris Wilson 6910be98a7SChris Wilson err = 0; 7010be98a7SChris Wilson out_import: 7110be98a7SChris Wilson i915_gem_object_put(to_intel_bo(import)); 7210be98a7SChris Wilson out_dmabuf: 7310be98a7SChris Wilson dma_buf_put(dmabuf); 7410be98a7SChris Wilson out: 7510be98a7SChris Wilson i915_gem_object_put(obj); 7610be98a7SChris Wilson return err; 7710be98a7SChris Wilson } 7810be98a7SChris Wilson 7910be98a7SChris Wilson static int igt_dmabuf_import(void *arg) 8010be98a7SChris Wilson { 8110be98a7SChris Wilson struct drm_i915_private *i915 = arg; 8210be98a7SChris Wilson struct drm_i915_gem_object *obj; 8310be98a7SChris Wilson struct dma_buf *dmabuf; 8410be98a7SChris Wilson void *obj_map, *dma_map; 85*6619ccf1SThomas Zimmermann struct dma_buf_map map; 8610be98a7SChris Wilson u32 pattern[] = { 0, 0xaa, 0xcc, 0x55, 0xff }; 8710be98a7SChris Wilson int err, i; 8810be98a7SChris Wilson 8910be98a7SChris Wilson dmabuf = mock_dmabuf(1); 9010be98a7SChris Wilson if (IS_ERR(dmabuf)) 9110be98a7SChris Wilson return PTR_ERR(dmabuf); 9210be98a7SChris Wilson 9310be98a7SChris Wilson obj = to_intel_bo(i915_gem_prime_import(&i915->drm, dmabuf)); 9410be98a7SChris Wilson if (IS_ERR(obj)) { 9510be98a7SChris Wilson pr_err("i915_gem_prime_import failed with err=%d\n", 9610be98a7SChris Wilson (int)PTR_ERR(obj)); 9710be98a7SChris Wilson err = PTR_ERR(obj); 9810be98a7SChris Wilson goto out_dmabuf; 9910be98a7SChris Wilson } 10010be98a7SChris Wilson 10110be98a7SChris Wilson if (obj->base.dev != &i915->drm) { 10210be98a7SChris Wilson pr_err("i915_gem_prime_import created a non-i915 object!\n"); 10310be98a7SChris Wilson err = -EINVAL; 10410be98a7SChris Wilson goto out_obj; 10510be98a7SChris Wilson } 10610be98a7SChris Wilson 10710be98a7SChris Wilson if (obj->base.size != PAGE_SIZE) { 10810be98a7SChris Wilson pr_err("i915_gem_prime_import is wrong size found %lld, expected %ld\n", 10910be98a7SChris Wilson (long long)obj->base.size, PAGE_SIZE); 11010be98a7SChris Wilson err = -EINVAL; 11110be98a7SChris Wilson goto out_obj; 11210be98a7SChris Wilson } 11310be98a7SChris Wilson 114*6619ccf1SThomas Zimmermann err = dma_buf_vmap(dmabuf, &map); 115*6619ccf1SThomas Zimmermann dma_map = err ? NULL : map.vaddr; 11610be98a7SChris Wilson if (!dma_map) { 11710be98a7SChris Wilson pr_err("dma_buf_vmap failed\n"); 11810be98a7SChris Wilson err = -ENOMEM; 11910be98a7SChris Wilson goto out_obj; 12010be98a7SChris Wilson } 12110be98a7SChris Wilson 12210be98a7SChris Wilson if (0) { /* Can not yet map dmabuf */ 12310be98a7SChris Wilson obj_map = i915_gem_object_pin_map(obj, I915_MAP_WB); 12410be98a7SChris Wilson if (IS_ERR(obj_map)) { 12510be98a7SChris Wilson err = PTR_ERR(obj_map); 12610be98a7SChris Wilson pr_err("i915_gem_object_pin_map failed with err=%d\n", err); 12710be98a7SChris Wilson goto out_dma_map; 12810be98a7SChris Wilson } 12910be98a7SChris Wilson 13010be98a7SChris Wilson for (i = 0; i < ARRAY_SIZE(pattern); i++) { 13110be98a7SChris Wilson memset(dma_map, pattern[i], PAGE_SIZE); 13210be98a7SChris Wilson if (memchr_inv(obj_map, pattern[i], PAGE_SIZE)) { 13310be98a7SChris Wilson err = -EINVAL; 13410be98a7SChris Wilson pr_err("imported vmap not all set to %x!\n", pattern[i]); 13510be98a7SChris Wilson i915_gem_object_unpin_map(obj); 13610be98a7SChris Wilson goto out_dma_map; 13710be98a7SChris Wilson } 13810be98a7SChris Wilson } 13910be98a7SChris Wilson 14010be98a7SChris Wilson for (i = 0; i < ARRAY_SIZE(pattern); i++) { 14110be98a7SChris Wilson memset(obj_map, pattern[i], PAGE_SIZE); 14210be98a7SChris Wilson if (memchr_inv(dma_map, pattern[i], PAGE_SIZE)) { 14310be98a7SChris Wilson err = -EINVAL; 14410be98a7SChris Wilson pr_err("exported vmap not all set to %x!\n", pattern[i]); 14510be98a7SChris Wilson i915_gem_object_unpin_map(obj); 14610be98a7SChris Wilson goto out_dma_map; 14710be98a7SChris Wilson } 14810be98a7SChris Wilson } 14910be98a7SChris Wilson 15010be98a7SChris Wilson i915_gem_object_unpin_map(obj); 15110be98a7SChris Wilson } 15210be98a7SChris Wilson 15310be98a7SChris Wilson err = 0; 15410be98a7SChris Wilson out_dma_map: 15510be98a7SChris Wilson dma_buf_vunmap(dmabuf, dma_map); 15610be98a7SChris Wilson out_obj: 15710be98a7SChris Wilson i915_gem_object_put(obj); 15810be98a7SChris Wilson out_dmabuf: 15910be98a7SChris Wilson dma_buf_put(dmabuf); 16010be98a7SChris Wilson return err; 16110be98a7SChris Wilson } 16210be98a7SChris Wilson 16310be98a7SChris Wilson static int igt_dmabuf_import_ownership(void *arg) 16410be98a7SChris Wilson { 16510be98a7SChris Wilson struct drm_i915_private *i915 = arg; 16610be98a7SChris Wilson struct drm_i915_gem_object *obj; 16710be98a7SChris Wilson struct dma_buf *dmabuf; 168*6619ccf1SThomas Zimmermann struct dma_buf_map map; 16910be98a7SChris Wilson void *ptr; 17010be98a7SChris Wilson int err; 17110be98a7SChris Wilson 17210be98a7SChris Wilson dmabuf = mock_dmabuf(1); 17310be98a7SChris Wilson if (IS_ERR(dmabuf)) 17410be98a7SChris Wilson return PTR_ERR(dmabuf); 17510be98a7SChris Wilson 176*6619ccf1SThomas Zimmermann err = dma_buf_vmap(dmabuf, &map); 177*6619ccf1SThomas Zimmermann ptr = err ? NULL : map.vaddr; 17810be98a7SChris Wilson if (!ptr) { 17910be98a7SChris Wilson pr_err("dma_buf_vmap failed\n"); 18010be98a7SChris Wilson err = -ENOMEM; 18110be98a7SChris Wilson goto err_dmabuf; 18210be98a7SChris Wilson } 18310be98a7SChris Wilson 18410be98a7SChris Wilson memset(ptr, 0xc5, PAGE_SIZE); 18510be98a7SChris Wilson dma_buf_vunmap(dmabuf, ptr); 18610be98a7SChris Wilson 18710be98a7SChris Wilson obj = to_intel_bo(i915_gem_prime_import(&i915->drm, dmabuf)); 18810be98a7SChris Wilson if (IS_ERR(obj)) { 18910be98a7SChris Wilson pr_err("i915_gem_prime_import failed with err=%d\n", 19010be98a7SChris Wilson (int)PTR_ERR(obj)); 19110be98a7SChris Wilson err = PTR_ERR(obj); 19210be98a7SChris Wilson goto err_dmabuf; 19310be98a7SChris Wilson } 19410be98a7SChris Wilson 19510be98a7SChris Wilson dma_buf_put(dmabuf); 19610be98a7SChris Wilson 19710be98a7SChris Wilson err = i915_gem_object_pin_pages(obj); 19810be98a7SChris Wilson if (err) { 19910be98a7SChris Wilson pr_err("i915_gem_object_pin_pages failed with err=%d\n", err); 20010be98a7SChris Wilson goto out_obj; 20110be98a7SChris Wilson } 20210be98a7SChris Wilson 20310be98a7SChris Wilson err = 0; 20410be98a7SChris Wilson i915_gem_object_unpin_pages(obj); 20510be98a7SChris Wilson out_obj: 20610be98a7SChris Wilson i915_gem_object_put(obj); 20710be98a7SChris Wilson return err; 20810be98a7SChris Wilson 20910be98a7SChris Wilson err_dmabuf: 21010be98a7SChris Wilson dma_buf_put(dmabuf); 21110be98a7SChris Wilson return err; 21210be98a7SChris Wilson } 21310be98a7SChris Wilson 21410be98a7SChris Wilson static int igt_dmabuf_export_vmap(void *arg) 21510be98a7SChris Wilson { 21610be98a7SChris Wilson struct drm_i915_private *i915 = arg; 21710be98a7SChris Wilson struct drm_i915_gem_object *obj; 21810be98a7SChris Wilson struct dma_buf *dmabuf; 219*6619ccf1SThomas Zimmermann struct dma_buf_map map; 22010be98a7SChris Wilson void *ptr; 22110be98a7SChris Wilson int err; 22210be98a7SChris Wilson 22310be98a7SChris Wilson obj = i915_gem_object_create_shmem(i915, PAGE_SIZE); 22410be98a7SChris Wilson if (IS_ERR(obj)) 22510be98a7SChris Wilson return PTR_ERR(obj); 22610be98a7SChris Wilson 227d8080976SDaniel Vetter dmabuf = i915_gem_prime_export(&obj->base, 0); 22810be98a7SChris Wilson if (IS_ERR(dmabuf)) { 22910be98a7SChris Wilson pr_err("i915_gem_prime_export failed with err=%d\n", 23010be98a7SChris Wilson (int)PTR_ERR(dmabuf)); 23110be98a7SChris Wilson err = PTR_ERR(dmabuf); 23210be98a7SChris Wilson goto err_obj; 23310be98a7SChris Wilson } 23410be98a7SChris Wilson i915_gem_object_put(obj); 23510be98a7SChris Wilson 236*6619ccf1SThomas Zimmermann err = dma_buf_vmap(dmabuf, &map); 237*6619ccf1SThomas Zimmermann ptr = err ? NULL : map.vaddr; 23810be98a7SChris Wilson if (!ptr) { 23910be98a7SChris Wilson pr_err("dma_buf_vmap failed\n"); 24010be98a7SChris Wilson err = -ENOMEM; 24110be98a7SChris Wilson goto out; 24210be98a7SChris Wilson } 24310be98a7SChris Wilson 24410be98a7SChris Wilson if (memchr_inv(ptr, 0, dmabuf->size)) { 24510be98a7SChris Wilson pr_err("Exported object not initialiased to zero!\n"); 24610be98a7SChris Wilson err = -EINVAL; 24710be98a7SChris Wilson goto out; 24810be98a7SChris Wilson } 24910be98a7SChris Wilson 25010be98a7SChris Wilson memset(ptr, 0xc5, dmabuf->size); 25110be98a7SChris Wilson 25210be98a7SChris Wilson err = 0; 25310be98a7SChris Wilson dma_buf_vunmap(dmabuf, ptr); 25410be98a7SChris Wilson out: 25510be98a7SChris Wilson dma_buf_put(dmabuf); 25610be98a7SChris Wilson return err; 25710be98a7SChris Wilson 25810be98a7SChris Wilson err_obj: 25910be98a7SChris Wilson i915_gem_object_put(obj); 26010be98a7SChris Wilson return err; 26110be98a7SChris Wilson } 26210be98a7SChris Wilson 26310be98a7SChris Wilson int i915_gem_dmabuf_mock_selftests(void) 26410be98a7SChris Wilson { 26510be98a7SChris Wilson static const struct i915_subtest tests[] = { 26610be98a7SChris Wilson SUBTEST(igt_dmabuf_export), 26710be98a7SChris Wilson SUBTEST(igt_dmabuf_import_self), 26810be98a7SChris Wilson SUBTEST(igt_dmabuf_import), 26910be98a7SChris Wilson SUBTEST(igt_dmabuf_import_ownership), 27010be98a7SChris Wilson SUBTEST(igt_dmabuf_export_vmap), 27110be98a7SChris Wilson }; 27210be98a7SChris Wilson struct drm_i915_private *i915; 27310be98a7SChris Wilson int err; 27410be98a7SChris Wilson 27510be98a7SChris Wilson i915 = mock_gem_device(); 27610be98a7SChris Wilson if (!i915) 27710be98a7SChris Wilson return -ENOMEM; 27810be98a7SChris Wilson 27910be98a7SChris Wilson err = i915_subtests(tests, i915); 28010be98a7SChris Wilson 28182be0d75SDaniel Vetter mock_destroy_device(i915); 28210be98a7SChris Wilson return err; 28310be98a7SChris Wilson } 28410be98a7SChris Wilson 28510be98a7SChris Wilson int i915_gem_dmabuf_live_selftests(struct drm_i915_private *i915) 28610be98a7SChris Wilson { 28710be98a7SChris Wilson static const struct i915_subtest tests[] = { 28810be98a7SChris Wilson SUBTEST(igt_dmabuf_export), 28910be98a7SChris Wilson }; 29010be98a7SChris Wilson 29110be98a7SChris Wilson return i915_subtests(tests, i915); 29210be98a7SChris Wilson } 293