On Tue, 26 Feb 2019 at 13:00, Tvrtko Ursulin <tvrtko.ursulin@xxxxxxxxxxxxxxx> wrote: > > > Hi, > > Just some quick comments, not a full review. Possibly a repeat of some > same comments from way back, not sure. > > On 14/02/2019 14:57, Matthew Auld wrote: > > Support memory regions, as defined by a given (start, end), and allow > > creating GEM objects which are backed by said region. > > > > Signed-off-by: Matthew Auld <matthew.auld@xxxxxxxxx> > > Signed-off-by: Abdiel Janulgue <abdiel.janulgue@xxxxxxxxxxxxxxx> > > Cc: Joonas Lahtinen <joonas.lahtinen@xxxxxxxxxxxxxxx> > > --- > > drivers/gpu/drm/i915/Makefile | 1 + > > drivers/gpu/drm/i915/i915_drv.h | 1 + > > drivers/gpu/drm/i915/i915_gem.c | 1 + > > drivers/gpu/drm/i915/i915_gem_object.h | 9 + > > drivers/gpu/drm/i915/intel_memory_region.c | 232 ++++++++++++++++++ > > drivers/gpu/drm/i915/intel_memory_region.h | 126 ++++++++++ > > drivers/gpu/drm/i915/selftests/huge_pages.c | 81 ++++++ > > .../drm/i915/selftests/i915_mock_selftests.h | 1 + > > .../drm/i915/selftests/intel_memory_region.c | 128 ++++++++++ > > .../gpu/drm/i915/selftests/mock_gem_device.c | 1 + > > drivers/gpu/drm/i915/selftests/mock_region.c | 71 ++++++ > > drivers/gpu/drm/i915/selftests/mock_region.h | 35 +++ > > 12 files changed, 687 insertions(+) > > create mode 100644 drivers/gpu/drm/i915/intel_memory_region.c > > create mode 100644 drivers/gpu/drm/i915/intel_memory_region.h > > create mode 100644 drivers/gpu/drm/i915/selftests/intel_memory_region.c > > create mode 100644 drivers/gpu/drm/i915/selftests/mock_region.c > > create mode 100644 drivers/gpu/drm/i915/selftests/mock_region.h > > > > diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile > > index e5ce813d1936..96be264fa382 100644 > > --- a/drivers/gpu/drm/i915/Makefile > > +++ b/drivers/gpu/drm/i915/Makefile > > @@ -88,6 +88,7 @@ i915-y += \ > > intel_engine_cs.o \ > > intel_hangcheck.o \ > > intel_lrc.o \ > > + intel_memory_region.o \ > > intel_mocs.o \ > > intel_ringbuffer.o \ > > intel_uncore.o \ > > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > > index 17fe942eaafa..0bea7d889284 100644 > > --- a/drivers/gpu/drm/i915/i915_drv.h > > +++ b/drivers/gpu/drm/i915/i915_drv.h > > @@ -72,6 +72,7 @@ > > #include "intel_wopcm.h" > > #include "intel_workarounds.h" > > #include "intel_uc.h" > > +#include "intel_memory_region.h" > > > > #include "i915_gem.h" > > #include "i915_gem_context.h" > > diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c > > index b421bc7a2e26..92768ab294a4 100644 > > --- a/drivers/gpu/drm/i915/i915_gem.c > > +++ b/drivers/gpu/drm/i915/i915_gem.c > > @@ -5706,4 +5706,5 @@ int i915_gem_object_attach_phys(struct drm_i915_gem_object *obj, int align) > > #include "selftests/i915_gem_object.c" > > #include "selftests/i915_gem_coherency.c" > > #include "selftests/i915_gem.c" > > +#include "selftests/intel_memory_region.c" > > #endif > > diff --git a/drivers/gpu/drm/i915/i915_gem_object.h b/drivers/gpu/drm/i915/i915_gem_object.h > > index fab040331cdb..ac52f61e8ad1 100644 > > --- a/drivers/gpu/drm/i915/i915_gem_object.h > > +++ b/drivers/gpu/drm/i915/i915_gem_object.h > > @@ -87,6 +87,15 @@ struct drm_i915_gem_object { > > > > const struct drm_i915_gem_object_ops *ops; > > > > + /** > > + * Memory region for this object. > > + */ > > + struct intel_memory_region *memory_region; > > + /** > > + * List of memory region blocks allocated for this object. > > + */ > > + struct list_head blocks; > > + > > struct { > > /** > > * @vma.lock: protect the list/tree of vmas > > diff --git a/drivers/gpu/drm/i915/intel_memory_region.c b/drivers/gpu/drm/i915/intel_memory_region.c > > new file mode 100644 > > index 000000000000..405d6d51194f > > --- /dev/null > > +++ b/drivers/gpu/drm/i915/intel_memory_region.c > > @@ -0,0 +1,232 @@ > > +/* > > + * Copyright © 2018 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 "intel_memory_region.h" > > +#include "i915_drv.h" > > + > > +static void > > +memory_region_free_pages(struct drm_i915_gem_object *obj, > > + struct sg_table *pages) > > +{ > > + > > + struct i915_gem_buddy_block *block, *on; > > + > > + lockdep_assert_held(&obj->memory_region->mm_lock); > > + > > + list_for_each_entry_safe(block, on, &obj->blocks, link) { > > + list_del_init(&block->link); > > + i915_gem_buddy_free(&obj->memory_region->mm, block); > > + } > > + > > + sg_free_table(pages); > > + kfree(pages); > > +} > > + > > +void > > +i915_memory_region_put_pages_buddy(struct drm_i915_gem_object *obj, > > + struct sg_table *pages) > > +{ > > + mutex_lock(&obj->memory_region->mm_lock); > > + memory_region_free_pages(obj, pages); > > + mutex_unlock(&obj->memory_region->mm_lock); > > + > > + obj->mm.dirty = false; > > +} > > + > > +int > > +i915_memory_region_get_pages_buddy(struct drm_i915_gem_object *obj) > > +{ > > + struct intel_memory_region *mem = obj->memory_region; > > + resource_size_t size = obj->base.size; > > + struct sg_table *st; > > + struct scatterlist *sg; > > + unsigned int sg_page_sizes; > > + unsigned long n_pages; > > + > > + GEM_BUG_ON(!IS_ALIGNED(size, mem->mm.min_size)); > > + GEM_BUG_ON(!list_empty(&obj->blocks)); > > + > > + st = kmalloc(sizeof(*st), GFP_KERNEL); > > + if (!st) > > + return -ENOMEM; > > + > > + n_pages = div64_u64(size, mem->mm.min_size); > > + > > + if (sg_alloc_table(st, n_pages, GFP_KERNEL)) { > > sg_alloc_table takes unsigned int for nents so if you need to do this > calculation in u64 you should probably add some checks against overflow. > Although it would probably be simpler and more robust to have it as > unsigned int and just check before hand the allocation request is not > exceeding the sg_table API capabilities. Yeah, the type stuff here is a little odd, but we do make sure that the number of pages doesn't exceed INT_MAX at object creation. > > > + kfree(st); > > + return -ENOMEM; > > + } > > + > > + sg = st->sgl; > > + st->nents = 0; > > + sg_page_sizes = 0; > > + > > + mutex_lock(&mem->mm_lock); > > + > > + do { > > + struct i915_gem_buddy_block *block; > > + unsigned int order; > > + u64 block_size; > > + u64 offset; > > + > > + order = fls(n_pages) - 1; > > + GEM_BUG_ON(order > mem->mm.max_order); > > + > > + do { > > + block = i915_gem_buddy_alloc(&mem->mm, order); > > + if (!IS_ERR(block)) > > + break; > > + > > + /* XXX: some kind of eviction pass, local to the device */ > > + if (!order--) > > Is it interesting to propagate the more specific error code returned by > i915_gem_buddy_alloc? It will either return -ENOMEM or -ENOSPC, although I'm now wondering if returning -ENOSPC from get_pages() is a bad idea. We normally just return -ENOMEM if we can't satisfy the request for the other backends... > > > + goto err_free_blocks; > > + } while (1); > > + > > + n_pages -= 1 << order; > > + > > + INIT_LIST_HEAD(&block->link); > > + list_add(&block->link, &obj->blocks); > > + > > + block_size = i915_gem_buddy_block_size(&mem->mm, block); > > + offset = i915_gem_buddy_block_offset(block); > > + > > + sg_dma_address(sg) = mem->region.start + offset; > > + sg_dma_len(sg) = block_size; > > + > > + sg->length = block_size; > > sg->dma_len and sg->length are unsigned int so again I think block_size > can follow with some limit checking earlier on. > > > + sg_page_sizes |= block_size; > > + st->nents++; > > If address of this block is consecutive block to the previous one you > can, considering the overflow of sg->dma_len and sg->length fields, > coalesce the two by just bumping the lengths and not incrementing the > st->nents++. That would make the i915_sg_trim below more effective. To > be fair I have no idea how likely are you to get consecutive blocks with > the buddy allocator so your decision. Yup, makes sense. > > Regards, > > Tvrtko > > > + > > + if (!n_pages) { > > + sg_mark_end(sg); > > + break; > > + } > > + > > + sg = __sg_next(sg); > > + } while (1); > > + > > + mutex_unlock(&mem->mm_lock); > > + > > + i915_sg_trim(st); > > + > > + __i915_gem_object_set_pages(obj, st, sg_page_sizes); > > + > > + return 0; > > + > > +err_free_blocks: > > + memory_region_free_pages(obj, st); > > + mutex_unlock(&mem->mm_lock); > > + return -ENOSPC; > > +} > > + > > +int i915_memory_region_init_buddy(struct intel_memory_region *mem) > > +{ > > + return i915_gem_buddy_init(&mem->mm, resource_size(&mem->region), > > + mem->min_page_size); > > +} > > + > > +void i915_memory_region_release_buddy(struct intel_memory_region *mem) > > +{ > > + i915_gem_buddy_fini(&mem->mm); > > +} > > + > > +struct drm_i915_gem_object * > > +i915_gem_object_create_region(struct intel_memory_region *mem, > > + resource_size_t size, > > + unsigned int flags) > > +{ > > + struct drm_i915_gem_object *obj; > > + > > + if (!mem) > > + return ERR_PTR(-ENODEV); > > + > > + size = round_up(size, mem->min_page_size); > > + > > + GEM_BUG_ON(!size); > > + GEM_BUG_ON(!IS_ALIGNED(size, I915_GTT_MIN_ALIGNMENT)); > > + > > + if (size >> PAGE_SHIFT > INT_MAX) > > + return ERR_PTR(-E2BIG); > > + > > + if (overflows_type(size, obj->base.size)) > > + return ERR_PTR(-E2BIG); > > + > > + obj = mem->ops->object_create(mem, size, flags); > > + if (IS_ERR(obj)) > > + return obj; > > + > > + INIT_LIST_HEAD(&obj->blocks); > > + obj->memory_region = mem; > > + > > + i915_gem_object_set_cache_coherency(obj, obj->cache_level); > > + > > + return obj; > > +} > > + > > +struct intel_memory_region * > > +intel_memory_region_create(struct drm_i915_private *i915, > > + resource_size_t start, > > + resource_size_t size, > > + resource_size_t min_page_size, > > + resource_size_t io_start, > > + const struct intel_memory_region_ops *ops) > > +{ > > + struct intel_memory_region *mem; > > + int err; > > + > > + mem = kzalloc(sizeof(*mem), GFP_KERNEL); > > + if (!mem) > > + return ERR_PTR(-ENOMEM); > > + > > + mem->i915 = i915; > > + mem->region = (struct resource)DEFINE_RES_MEM(start, size); > > + mem->io_start = io_start; > > + mem->min_page_size = min_page_size; > > + mem->ops = ops; > > + > > + mutex_init(&mem->mm_lock); > > + > > + if (ops->init) { > > + err = ops->init(mem); > > + if (err) { > > + kfree(mem); > > + mem = ERR_PTR(err); > > + } > > + } > > + > > + return mem; > > +} > > + > > +void > > +intel_memory_region_destroy(struct intel_memory_region *mem) > > +{ > > + if (mem->ops->release) > > + mem->ops->release(mem); > > + > > + kfree(mem); > > +} > > + > > +#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) > > +#include "selftests/mock_region.c" > > +#endif > > diff --git a/drivers/gpu/drm/i915/intel_memory_region.h b/drivers/gpu/drm/i915/intel_memory_region.h > > new file mode 100644 > > index 000000000000..6d8a954ca75e > > --- /dev/null > > +++ b/drivers/gpu/drm/i915/intel_memory_region.h > > @@ -0,0 +1,126 @@ > > +/* > > + * Copyright © 2018 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 __INTEL_MEMORY_REGION_H__ > > +#define __INTEL_MEMORY_REGION_H__ > > + > > +#include <linux/ioport.h> > > +#include <linux/mutex.h> > > +#include <linux/io-mapping.h> > > + > > +#include "i915_gem_buddy.h" > > + > > +struct drm_i915_private; > > +struct drm_i915_gem_object; > > +struct intel_memory_region; > > +struct sg_table; > > + > > +/** > > + * Base memory type > > + */ > > +enum intel_memory_type { > > + INTEL_SMEM = 0, > > + INTEL_LMEM, > > + INTEL_STOLEN, > > +}; > > + > > +enum intel_region_id { > > + INTEL_MEMORY_SMEM = 0, > > + INTEL_MEMORY_LMEM, > > + INTEL_MEMORY_STOLEN, > > + INTEL_MEMORY_UKNOWN, /* Should be last */ > > +}; > > + > > +#define REGION_SMEM BIT(INTEL_MEMORY_SMEM) > > +#define REGION_LMEM BIT(INTEL_MEMORY_LMEM) > > +#define REGION_STOLEN BIT(INTEL_MEMORY_STOLEN) > > + > > +#define INTEL_MEMORY_TYPE_SHIFT 16 > > + > > +#define MEMORY_TYPE_FROM_REGION(r) (ilog2(r >> INTEL_MEMORY_TYPE_SHIFT)) > > +#define MEMORY_INSTANCE_FROM_REGION(r) (ilog2(r & 0xffff)) > > + > > +/** > > + * Memory regions encoded as type | instance > > + */ > > +static const u32 intel_region_map[] = { > > + [INTEL_MEMORY_SMEM] = BIT(INTEL_SMEM + INTEL_MEMORY_TYPE_SHIFT) | BIT(0), > > + [INTEL_MEMORY_LMEM] = BIT(INTEL_LMEM + INTEL_MEMORY_TYPE_SHIFT) | BIT(0), > > + [INTEL_MEMORY_STOLEN] = BIT(INTEL_STOLEN + INTEL_MEMORY_TYPE_SHIFT) | BIT(0), > > +}; > > + > > +struct intel_memory_region_ops { > > + unsigned int flags; > > + > > + int (*init)(struct intel_memory_region *); > > + void (*release)(struct intel_memory_region *); > > + > > + struct drm_i915_gem_object * > > + (*object_create)(struct intel_memory_region *, > > + resource_size_t, > > + unsigned int); > > +}; > > + > > +struct intel_memory_region { > > + struct drm_i915_private *i915; > > + > > + const struct intel_memory_region_ops *ops; > > + > > + struct io_mapping iomap; > > + struct resource region; > > + > > + struct i915_gem_buddy_mm mm; > > + struct mutex mm_lock; > > + > > + resource_size_t io_start; > > + resource_size_t min_page_size; > > + > > + unsigned int type; > > + unsigned int instance; > > + unsigned int id; > > +}; > > + > > +int i915_memory_region_init_buddy(struct intel_memory_region *mem); > > +void i915_memory_region_release_buddy(struct intel_memory_region *mem); > > + > > +int i915_memory_region_get_pages_buddy(struct drm_i915_gem_object *obj); > > +void i915_memory_region_put_pages_buddy(struct drm_i915_gem_object *obj, > > + struct sg_table *pages); > > + > > +struct intel_memory_region * > > +intel_memory_region_create(struct drm_i915_private *i915, > > + resource_size_t start, > > + resource_size_t size, > > + resource_size_t min_page_size, > > + resource_size_t io_start, > > + const struct intel_memory_region_ops *ops); > > +void > > +intel_memory_region_destroy(struct intel_memory_region *mem); > > + > > +struct drm_i915_gem_object * > > +i915_gem_object_create_region(struct intel_memory_region *mem, > > + resource_size_t size, > > + unsigned int flags); > > + > > +#endif > > diff --git a/drivers/gpu/drm/i915/selftests/huge_pages.c b/drivers/gpu/drm/i915/selftests/huge_pages.c > > index b6d84939592b..b0c8b4955f14 100644 > > --- a/drivers/gpu/drm/i915/selftests/huge_pages.c > > +++ b/drivers/gpu/drm/i915/selftests/huge_pages.c > > @@ -458,6 +458,86 @@ static int igt_mock_exhaust_device_supported_pages(void *arg) > > return err; > > } > > > > + > > +static int igt_mock_memory_region_huge_pages(void *arg) > > +{ > > + struct i915_hw_ppgtt *ppgtt = arg; > > + struct drm_i915_private *i915 = ppgtt->vm.i915; > > + unsigned long supported = INTEL_INFO(i915)->page_sizes; > > + struct intel_memory_region *mem; > > + struct drm_i915_gem_object *obj; > > + struct i915_vma *vma; > > + int bit; > > + int err = 0; > > + > > + mem = mock_region_create(i915, 0, SZ_2G, > > + I915_GTT_PAGE_SIZE_4K, 0); > > + if (IS_ERR(mem)) { > > + pr_err("failed to create memory region\n"); > > + return PTR_ERR(mem); > > + } > > + > > + for_each_set_bit(bit, &supported, ilog2(I915_GTT_MAX_PAGE_SIZE) + 1) { > > + unsigned int page_size = BIT(bit); > > + resource_size_t phys; > > + > > + obj = i915_gem_object_create_region(mem, page_size, 0); > > + if (IS_ERR(obj)) { > > + err = PTR_ERR(obj); > > + goto out_destroy_device; > > + } > > + > > + pr_info("memory region start(%pa)\n", > > + &obj->memory_region->region.start); > > + pr_info("creating object, size=%x\n", page_size); > > + > > + vma = i915_vma_instance(obj, &ppgtt->vm, NULL); > > + if (IS_ERR(vma)) { > > + err = PTR_ERR(vma); > > + goto out_put; > > + } > > + > > + err = i915_vma_pin(vma, 0, 0, PIN_USER); > > + if (err) > > + goto out_close; > > + > > + phys = i915_gem_object_get_dma_address(obj, 0); > > + if (!IS_ALIGNED(phys, page_size)) { > > + pr_err("memory region misaligned(%pa)\n", &phys); > > + err = -EINVAL; > > + goto out_close; > > + } > > + > > + if (vma->page_sizes.gtt != page_size) { > > + pr_err("page_sizes.gtt=%u, expected=%u\n", > > + vma->page_sizes.gtt, page_size); > > + err = -EINVAL; > > + goto out_unpin; > > + } > > + > > + i915_vma_unpin(vma); > > + i915_vma_close(vma); > > + > > + i915_gem_object_put(obj); > > + } > > + > > + goto out_destroy_device; > > + > > +out_unpin: > > + i915_vma_unpin(vma); > > +out_close: > > + i915_vma_close(vma); > > +out_put: > > + i915_gem_object_put(obj); > > +out_destroy_device: > > + mutex_unlock(&i915->drm.struct_mutex); > > + i915_gem_drain_freed_objects(i915); > > + mutex_lock(&i915->drm.struct_mutex); > > + intel_memory_region_destroy(mem); > > + > > + return err; > > +} > > + > > static int igt_mock_ppgtt_misaligned_dma(void *arg) > > { > > struct i915_hw_ppgtt *ppgtt = arg; > > @@ -1697,6 +1777,7 @@ int i915_gem_huge_page_mock_selftests(void) > > { > > static const struct i915_subtest tests[] = { > > SUBTEST(igt_mock_exhaust_device_supported_pages), > > + SUBTEST(igt_mock_memory_region_huge_pages), > > SUBTEST(igt_mock_ppgtt_misaligned_dma), > > SUBTEST(igt_mock_ppgtt_huge_fill), > > SUBTEST(igt_mock_ppgtt_64K), > > diff --git a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h > > index 984e07ed65e5..3e34ee2255db 100644 > > --- a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h > > +++ b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h > > @@ -25,3 +25,4 @@ selftest(gtt, i915_gem_gtt_mock_selftests) > > selftest(hugepages, i915_gem_huge_page_mock_selftests) > > selftest(contexts, i915_gem_context_mock_selftests) > > selftest(buddy, i915_gem_buddy_mock_selftests) > > +selftest(memory_region, intel_memory_region_mock_selftests) > > diff --git a/drivers/gpu/drm/i915/selftests/intel_memory_region.c b/drivers/gpu/drm/i915/selftests/intel_memory_region.c > > new file mode 100644 > > index 000000000000..2b8d28216d87 > > --- /dev/null > > +++ b/drivers/gpu/drm/i915/selftests/intel_memory_region.c > > @@ -0,0 +1,128 @@ > > +/* > > + * Copyright © 2018 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_context.h" > > +#include "mock_drm.h" > > + > > +static void close_objects(struct list_head *objects) > > +{ > > + struct drm_i915_gem_object *obj, *on; > > + > > + list_for_each_entry_safe(obj, on, objects, st_link) { > > + if (i915_gem_object_has_pinned_pages(obj)) > > + i915_gem_object_unpin_pages(obj); > > + /* No polluting the memory region between tests */ > > + __i915_gem_object_put_pages(obj, I915_MM_NORMAL); > > + i915_gem_object_put(obj); > > + list_del(&obj->st_link); > > + } > > +} > > + > > +static int igt_mock_fill(void *arg) > > +{ > > + struct intel_memory_region *mem = arg; > > + resource_size_t total = resource_size(&mem->region); > > + resource_size_t page_size; > > + resource_size_t rem; > > + unsigned long max_pages; > > + unsigned long page_num; > > + LIST_HEAD(objects); > > + int err = 0; > > + > > + page_size = mem->mm.min_size; > > + max_pages = total / page_size; > > + rem = total; > > + > > + for_each_prime_number_from(page_num, 1, max_pages) { > > + resource_size_t size = page_num * page_size; > > + struct drm_i915_gem_object *obj; > > + > > + obj = i915_gem_object_create_region(mem, size, 0); > > + if (IS_ERR(obj)) { > > + err = PTR_ERR(obj); > > + break; > > + } > > + > > + err = i915_gem_object_pin_pages(obj); > > + if (err) { > > + i915_gem_object_put(obj); > > + break; > > + } > > + > > + list_add(&obj->st_link, &objects); > > + rem -= size; > > + } > > + > > + if (err == -ENOMEM) > > + err = 0; > > + if (err == -ENOSPC) { > > + if (page_num * page_size <= rem) { > > + pr_err("igt_mock_fill failed, space still left in region\n"); > > + err = -EINVAL; > > + } else { > > + err = 0; > > + } > > + } > > + > > + close_objects(&objects); > > + > > + return err; > > +} > > + > > +int intel_memory_region_mock_selftests(void) > > +{ > > + static const struct i915_subtest tests[] = { > > + SUBTEST(igt_mock_fill), > > + }; > > + struct intel_memory_region *mem; > > + struct drm_i915_private *i915; > > + int err; > > + > > + i915 = mock_gem_device(); > > + if (!i915) > > + return -ENOMEM; > > + > > + mem = mock_region_create(i915, 0, SZ_2G, > > + I915_GTT_PAGE_SIZE_4K, 0); > > + if (IS_ERR(mem)) { > > + pr_err("failed to create memory region\n"); > > + err = PTR_ERR(mem); > > + goto out_unref; > > + } > > + > > + mutex_lock(&i915->drm.struct_mutex); > > + err = i915_subtests(tests, mem); > > + mutex_unlock(&i915->drm.struct_mutex); > > + > > + i915_gem_drain_freed_objects(i915); > > + intel_memory_region_destroy(mem); > > + > > +out_unref: > > + drm_dev_put(&i915->drm); > > + > > + return err; > > +} > > diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c > > index 876f4e6dadac..f8901cd12180 100644 > > --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c > > +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c > > @@ -32,6 +32,7 @@ > > #include "mock_gem_object.h" > > #include "mock_gtt.h" > > #include "mock_uncore.h" > > +#include "mock_region.h" > > > > void mock_device_flush(struct drm_i915_private *i915) > > { > > diff --git a/drivers/gpu/drm/i915/selftests/mock_region.c b/drivers/gpu/drm/i915/selftests/mock_region.c > > new file mode 100644 > > index 000000000000..2c83711f780d > > --- /dev/null > > +++ b/drivers/gpu/drm/i915/selftests/mock_region.c > > @@ -0,0 +1,71 @@ > > +/* > > + * Copyright © 2019 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_region.h" > > + > > +static const struct drm_i915_gem_object_ops mock_region_obj_ops = { > > + .get_pages = i915_memory_region_get_pages_buddy, > > + .put_pages = i915_memory_region_put_pages_buddy, > > +}; > > + > > +static struct drm_i915_gem_object * > > +mock_object_create(struct intel_memory_region *mem, > > + resource_size_t size, > > + unsigned int flags) > > +{ > > + struct drm_i915_private *i915 = mem->i915; > > + struct drm_i915_gem_object *obj; > > + > > + if (size > BIT(mem->mm.max_order) * mem->mm.min_size) > > + return ERR_PTR(-E2BIG); > > + > > + obj = i915_gem_object_alloc(i915); > > + if (!obj) > > + return ERR_PTR(-ENOMEM); > > + > > + drm_gem_private_object_init(&i915->drm, &obj->base, size); > > + i915_gem_object_init(obj, &mock_region_obj_ops); > > + > > + obj->read_domains = I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT; > > + obj->cache_level = HAS_LLC(i915) ? I915_CACHE_LLC : I915_CACHE_NONE; > > + > > + return obj; > > +} > > + > > +static const struct intel_memory_region_ops mock_region_ops = { > > + .init = i915_memory_region_init_buddy, > > + .release = i915_memory_region_release_buddy, > > + .object_create = mock_object_create, > > +}; > > + > > +struct intel_memory_region * > > +mock_region_create(struct drm_i915_private *i915, > > + resource_size_t start, > > + resource_size_t size, > > + resource_size_t min_page_size, > > + resource_size_t io_start) > > +{ > > + return intel_memory_region_create(i915, start, size, min_page_size, > > + io_start, &mock_region_ops); > > +} > > diff --git a/drivers/gpu/drm/i915/selftests/mock_region.h b/drivers/gpu/drm/i915/selftests/mock_region.h > > new file mode 100644 > > index 000000000000..47718313fa58 > > --- /dev/null > > +++ b/drivers/gpu/drm/i915/selftests/mock_region.h > > @@ -0,0 +1,35 @@ > > +/* > > + * Copyright © 2019 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_REGION_H > > +#define __MOCK_REGION_H > > + > > +struct intel_memory_region * > > +mock_region_create(struct drm_i915_private *i915, > > + resource_size_t start, > > + resource_size_t size, > > + resource_size_t min_page_size, > > + resource_size_t io_start); > > + > > +#endif /* !__MOCK_REGION_H */ > > > _______________________________________________ > Intel-gfx mailing list > Intel-gfx@xxxxxxxxxxxxxxxxxxxxx > https://lists.freedesktop.org/mailman/listinfo/intel-gfx _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx