On 20 December 2016 at 13:08, Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> wrote: > Check that we can create both dmabuf and objects from dmabuf. > > Signed-off-by: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> > --- > drivers/gpu/drm/i915/i915_gem_dmabuf.c | 5 + > drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c | 297 +++++++++++++++++++++ > .../gpu/drm/i915/selftests/i915_mock_selftests.h | 1 + > drivers/gpu/drm/i915/selftests/mock_dmabuf.c | 176 ++++++++++++ > drivers/gpu/drm/i915/selftests/mock_dmabuf.h | 43 +++ > 5 files changed, 522 insertions(+) > create mode 100644 drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c > create mode 100644 drivers/gpu/drm/i915/selftests/mock_dmabuf.c > create mode 100644 drivers/gpu/drm/i915/selftests/mock_dmabuf.h > > diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c > index d037adcda6f2..3e276eee0450 100644 > --- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c > +++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c > @@ -307,3 +307,8 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev, > > return ERR_PTR(ret); > } > + > +#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) > +#include "selftests/mock_dmabuf.c" > +#include "selftests/i915_gem_dmabuf.c" > +#endif > diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c > new file mode 100644 > index 000000000000..115c477978f7 > --- /dev/null > +++ b/drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c > @@ -0,0 +1,297 @@ > +/* > + * Copyright © 2016 Intel Corporation > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the "Software"), > + * to deal in the Software without restriction, including without limitation > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > + * and/or sell copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice (including the next > + * paragraph) shall be included in all copies or substantial portions of the > + * Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS > + * IN THE SOFTWARE. > + * > + */ > + > +#include "i915_selftest.h" > + > +#include "mock_gem_device.h" > +#include "mock_dmabuf.h" > + > +static int igt_dmabuf_export(void *arg) > +{ > + struct drm_i915_private *i915 = arg; > + struct drm_i915_gem_object *obj; > + struct dma_buf *dmabuf; > + int err; > + > + obj = i915_gem_object_create(i915, PAGE_SIZE); > + if (IS_ERR(obj)) > + return PTR_ERR(obj); > + > + dmabuf = i915_gem_prime_export(&i915->drm, &obj->base, 0); > + if (IS_ERR(dmabuf)) { > + pr_err("i915_gem_prime_export failed with err=%d\n", > + (int)PTR_ERR(dmabuf)); > + err = PTR_ERR(dmabuf); > + goto err; > + } > + > + err = 0; > + dma_buf_put(dmabuf); > +err: > + i915_gem_object_put(obj); > + return err; > +} > + > +static int igt_dmabuf_import_self(void *arg) > +{ > + struct drm_i915_private *i915 = arg; > + struct drm_i915_gem_object *obj; > + struct drm_gem_object *import; > + struct dma_buf *dmabuf; > + int err; > + > + obj = i915_gem_object_create(i915, PAGE_SIZE); > + if (IS_ERR(obj)) > + return PTR_ERR(obj); > + > + dmabuf = i915_gem_prime_export(&i915->drm, &obj->base, 0); > + if (IS_ERR(dmabuf)) { > + pr_err("i915_gem_prime_export failed with err=%d\n", > + (int)PTR_ERR(dmabuf)); > + err = PTR_ERR(dmabuf); > + goto err; > + } > + > + import = i915_gem_prime_import(&i915->drm, dmabuf); > + if (IS_ERR(import)) { > + pr_err("i915_gem_prime_import failed with err=%d\n", > + (int)PTR_ERR(import)); > + err = PTR_ERR(import); > + goto err_dmabuf; > + } > + > + if (import != &obj->base) { > + pr_err("i915_gem_prime_import created a new object!\n"); > + err = -EINVAL; > + goto err_import; > + } > + > + err = 0; > +err_import: > + i915_gem_object_put(to_intel_bo(import)); > +err_dmabuf: > + dma_buf_put(dmabuf); > +err: > + i915_gem_object_put(obj); > + return err; > +} > + > +static int igt_dmabuf_import(void *arg) > +{ > + struct drm_i915_private *i915 = arg; > + struct drm_i915_gem_object *obj; > + struct dma_buf *dmabuf; > + void *obj_map, *dma_map; > + u32 pattern[] = { 0, 0xaa, 0xcc, 0x55, 0xff }; > + int err, i; > + > + dmabuf = mock_dmabuf(1); This looks like it's going to blow up if it returns NULL, which it can. See the other call site too. > + if (IS_ERR(dmabuf)) > + return PTR_ERR(dmabuf); > + > + obj = to_intel_bo(i915_gem_prime_import(&i915->drm, dmabuf)); > + if (IS_ERR(obj)) { > + pr_err("i915_gem_prime_import failed with err=%d\n", > + (int)PTR_ERR(obj)); > + err = PTR_ERR(obj); > + goto err_dmabuf; > + } > + > + if (obj->base.dev != &i915->drm) { > + pr_err("i915_gem_prime_import created a non-i915 object!\n"); > + err = -EINVAL; > + goto err_obj; > + } > + > + if (obj->base.size != PAGE_SIZE) { > + pr_err("i915_gem_prime_import is wrong size found %lld, expected %ld\n", > + (long long)obj->base.size, PAGE_SIZE); > + err = -EINVAL; > + goto err_obj; > + } > + > + dma_map = dma_buf_vmap(dmabuf); > + if (!dma_map) { > + pr_err("dma_buf_vmap failed\n"); > + err = -ENOMEM; > + goto err_obj; > + } > + > + if (0) { > + /* Can not yet map dmabuf */ > + obj_map = i915_gem_object_pin_map(obj, I915_MAP_WB); > + if (IS_ERR(obj_map)) { > + err = PTR_ERR(obj_map); > + pr_err("i915_gem_object_pin_map failed with err=%d\n", err); > + goto err_dma_map; > + } > + > + for (i = 0; i < ARRAY_SIZE(pattern); i++) { > + memset(dma_map, pattern[i], PAGE_SIZE); > + if (memchr_inv(obj_map, pattern[i], PAGE_SIZE)) { > + err = -EINVAL; > + pr_err("imported vmap not all set to %x!\n", pattern[i]); > + i915_gem_object_unpin_map(obj); > + goto err_dma_map; > + } > + } > + > + for (i = 0; i < ARRAY_SIZE(pattern); i++) { > + memset(obj_map, pattern[i], PAGE_SIZE); > + if (memchr_inv(dma_map, pattern[i], PAGE_SIZE)) { > + err = -EINVAL; > + pr_err("exported vmap not all set to %x!\n", pattern[i]); > + i915_gem_object_unpin_map(obj); > + goto err_dma_map; > + } > + } i915_gem_object_unpin_map(obj); > + } > + > + err = 0; > +err_dma_map: > + dma_buf_vunmap(dmabuf, dma_map); > +err_obj: > + i915_gem_object_put(obj); > +err_dmabuf: > + dma_buf_put(dmabuf); > + return err; > +} > + > +static int igt_dmabuf_import_ownership(void *arg) > +{ > + struct drm_i915_private *i915 = arg; > + struct drm_i915_gem_object *obj; > + struct dma_buf *dmabuf; > + void *ptr; > + int err; > + > + dmabuf = mock_dmabuf(1); > + if (IS_ERR(dmabuf)) > + return PTR_ERR(dmabuf); > + > + ptr = dma_buf_vmap(dmabuf); > + if (!ptr) { > + pr_err("dma_buf_vmap failed\n"); > + err = -ENOMEM; > + goto err_dmabuf; > + } > + > + memset(ptr, 0xc5, PAGE_SIZE); > + dma_buf_vunmap(dmabuf, ptr); > + > + obj = to_intel_bo(i915_gem_prime_import(&i915->drm, dmabuf)); > + if (IS_ERR(obj)) { > + pr_err("i915_gem_prime_import failed with err=%d\n", > + (int)PTR_ERR(obj)); > + err = PTR_ERR(obj); > + goto err_dmabuf; > + } > + > + dma_buf_put(dmabuf); > + > + err = i915_gem_object_pin_pages(obj); > + if (err) { > + pr_err("i915_gem_object_pin_pages failed with err=%d\n", err); > + goto err_obj; > + } > + > + err = 0; > + i915_gem_object_unpin_pages(obj); > +err_obj: > + i915_gem_object_put(obj); > + return err; > + > +err_dmabuf: > + dma_buf_put(dmabuf); > + return err; > +} > + > +static int igt_dmabuf_export_vmap(void *arg) > +{ > + struct drm_i915_private *i915 = arg; > + struct drm_i915_gem_object *obj; > + struct dma_buf *dmabuf; > + void *ptr; > + int err; > + > + obj = i915_gem_object_create(i915, PAGE_SIZE); > + if (IS_ERR(obj)) > + return PTR_ERR(obj); > + > + dmabuf = i915_gem_prime_export(&i915->drm, &obj->base, 0); > + if (IS_ERR(dmabuf)) { > + pr_err("i915_gem_prime_export failed with err=%d\n", > + (int)PTR_ERR(dmabuf)); > + err = PTR_ERR(dmabuf); > + goto err_obj; > + } > + i915_gem_object_put(obj); > + > + ptr = dma_buf_vmap(dmabuf); > + if (IS_ERR(ptr)) { > + err = PTR_ERR(ptr); > + pr_err("dma_buf_vmap failed with err=%d\n", err); > + goto err; > + } > + > + if(memchr_inv(ptr, 0, dmabuf->size)) { > + pr_err("Exported object no initialiased to zero!\n"); s/no initialiased/not initialised/ > + err = -EINVAL; > + goto err; > + } > + > + memset(ptr, 0xc5, dmabuf->size); > + > + err = 0; > + dma_buf_vunmap(dmabuf, ptr); > +err: > + dma_buf_put(dmabuf); > + return err; > + > +err_obj: > + i915_gem_object_put(obj); > + return err; > +} > + > +int i915_gem_dmabuf_selftest(void) > +{ > + static const struct i915_subtest tests[] = { > + SUBTEST(igt_dmabuf_export), > + SUBTEST(igt_dmabuf_import_self), > + SUBTEST(igt_dmabuf_import), > + SUBTEST(igt_dmabuf_import_ownership), > + SUBTEST(igt_dmabuf_export_vmap), > + }; > + struct drm_i915_private *i915; > + int err; > + > + i915 = mock_gem_device(); > + if (!i915) > + return -ENOMEM; > + > + err = i915_subtests(tests, i915); > + > + drm_dev_unref(&i915->drm); > + return err; > +} > diff --git a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h > index 390af5cd895e..417bcfa3cdba 100644 > --- a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h > +++ b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h > @@ -14,3 +14,4 @@ selftest(uncore, intel_uncore_mock_selftests) > selftest(breadcrumbs, intel_breadcrumbs_selftest) > selftest(requests, i915_gem_request_selftest) > selftest(objects, i915_gem_object_selftests) > +selftest(dmabuf, i915_gem_dmabuf_selftest) > diff --git a/drivers/gpu/drm/i915/selftests/mock_dmabuf.c b/drivers/gpu/drm/i915/selftests/mock_dmabuf.c > new file mode 100644 > index 000000000000..515691779540 > --- /dev/null > +++ b/drivers/gpu/drm/i915/selftests/mock_dmabuf.c > @@ -0,0 +1,176 @@ > +/* > + * Copyright © 2016 Intel Corporation > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the "Software"), > + * to deal in the Software without restriction, including without limitation > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > + * and/or sell copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice (including the next > + * paragraph) shall be included in all copies or substantial portions of the > + * Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS > + * IN THE SOFTWARE. > + * > + */ > + > +#include "mock_dmabuf.h" > + > +static struct sg_table *mock_map_dma_buf(struct dma_buf_attachment *attachment, > + enum dma_data_direction dir) > +{ > + struct mock_dmabuf *mock = to_mock(attachment->dmabuf); > + struct sg_table *st; > + struct scatterlist *sg; > + int i, err; > + > + st = kmalloc(sizeof(*st), GFP_KERNEL); > + if (!st) > + return ERR_PTR(-ENOMEM); > + > + err = sg_alloc_table(st, mock->npages, GFP_KERNEL); > + if (err) > + goto err_free; > + > + sg = st->sgl; > + for (i = 0; i < mock->npages; i++) { > + sg_set_page(sg, mock->pages[i], PAGE_SIZE, 0); > + sg = sg_next(sg); > + } > + > + if (!dma_map_sg(attachment->dev, st->sgl, st->nents, dir)) { > + err = -ENOMEM; > + goto err_st; > + } > + > + return st; > + > +err_st: > + sg_free_table(st); > +err_free: > + kfree(st); > + return ERR_PTR(err); > +} > + > +static void mock_unmap_dma_buf(struct dma_buf_attachment *attachment, > + struct sg_table *st, > + enum dma_data_direction dir) > +{ > + dma_unmap_sg(attachment->dev, st->sgl, st->nents, dir); > + sg_free_table(st); > + kfree(st); > +} > + > +static void mock_dmabuf_release(struct dma_buf *dma_buf) > +{ > + struct mock_dmabuf *mock = to_mock(dma_buf); > + int i; > + > + for (i = 0; i < mock->npages; i++) > + put_page(mock->pages[i]); > + > + kfree(mock); > +} > + > +static void *mock_dmabuf_vmap(struct dma_buf *dma_buf) > +{ > + struct mock_dmabuf *mock = to_mock(dma_buf); > + > + return vm_map_ram(mock->pages, mock->npages, 0, PAGE_KERNEL); > +} > + > +static void mock_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr) > +{ > + struct mock_dmabuf *mock = to_mock(dma_buf); > + > + vm_unmap_ram(vaddr, mock->npages); > +} > + > +static void *mock_dmabuf_kmap_atomic(struct dma_buf *dma_buf, unsigned long page_num) > +{ > + struct mock_dmabuf *mock = to_mock(dma_buf); > + > + return kmap_atomic(mock->pages[page_num]); > +} > + > +static void mock_dmabuf_kunmap_atomic(struct dma_buf *dma_buf, unsigned long page_num, void *addr) > +{ > + kunmap_atomic(addr); > +} > + > +static void *mock_dmabuf_kmap(struct dma_buf *dma_buf, unsigned long page_num) > +{ > + struct mock_dmabuf *mock = to_mock(dma_buf); > + > + return kmap(mock->pages[page_num]); > +} > + > +static void mock_dmabuf_kunmap(struct dma_buf *dma_buf, unsigned long page_num, void *addr) > +{ > + struct mock_dmabuf *mock = to_mock(dma_buf); > + > + return kunmap(mock->pages[page_num]); > +} > + > +static int mock_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma) > +{ > + return -ENODEV; > +} > + > +static const struct dma_buf_ops mock_dmabuf_ops = { > + .map_dma_buf = mock_map_dma_buf, > + .unmap_dma_buf = mock_unmap_dma_buf, > + .release = mock_dmabuf_release, > + .kmap = mock_dmabuf_kmap, > + .kmap_atomic = mock_dmabuf_kmap_atomic, > + .kunmap = mock_dmabuf_kunmap, > + .kunmap_atomic = mock_dmabuf_kunmap_atomic, > + .mmap = mock_dmabuf_mmap, > + .vmap = mock_dmabuf_vmap, > + .vunmap = mock_dmabuf_vunmap, > +}; > + > +static struct dma_buf *mock_dmabuf(int npages) > +{ > + struct mock_dmabuf *mock; > + DEFINE_DMA_BUF_EXPORT_INFO(exp_info); > + struct dma_buf *dmabuf; > + int i; > + > + mock = kmalloc(sizeof(*mock) + npages * sizeof(struct page *), > + GFP_KERNEL); > + if (!mock) > + return ERR_PTR(-ENOMEM); > + > + mock->npages = npages; > + for (i = 0; i < npages; i++) { > + mock->pages[i] = alloc_page(GFP_KERNEL); > + if (!mock->pages[i]) > + goto err; > + } > + > + exp_info.ops = &mock_dmabuf_ops; > + exp_info.size = npages * PAGE_SIZE; > + exp_info.flags = O_CLOEXEC; > + exp_info.priv = mock; > + > + dmabuf = dma_buf_export(&exp_info); > + if (IS_ERR(dmabuf)) > + goto err; > + > + return dmabuf; > + > +err: > + while (i--) > + put_page(mock->pages[i]); > + kfree(mock); > + return NULL; > +} > diff --git a/drivers/gpu/drm/i915/selftests/mock_dmabuf.h b/drivers/gpu/drm/i915/selftests/mock_dmabuf.h > new file mode 100644 > index 000000000000..bb5aaebcc80e > --- /dev/null > +++ b/drivers/gpu/drm/i915/selftests/mock_dmabuf.h > @@ -0,0 +1,43 @@ > + > +/* > + * Copyright © 2016 Intel Corporation > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the "Software"), > + * to deal in the Software without restriction, including without limitation > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > + * and/or sell copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice (including the next > + * paragraph) shall be included in all copies or substantial portions of the > + * Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS > + * IN THE SOFTWARE. > + * > + */ > + > +#ifndef __MOCK_DMABUF_H__ > +#define __MOCK_DMABUF_H__ > + > +#include "mock_dmabuf.h" > + > +struct dma_buf; > + > +struct mock_dmabuf { > + int npages; > + struct page *pages[]; > +}; > + > +static struct mock_dmabuf *to_mock(struct dma_buf *buf) > +{ > + return buf->priv; We forward declare struct dma_buf, and yet we can access the priv member here ? Otherwise: Reviewed-by: Matthew Auld <matthew.auld@xxxxxxxxx> _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx