All of lore.kernel.org
 help / color / mirror / Atom feed
From: Matthew Auld <matthew.auld@intel.com>
To: intel-gfx@lists.freedesktop.org
Cc: daniel.vetter@ffwll.ch
Subject: [PATCH 04/22] drm/i915/region: support continuous allocations
Date: Fri, 27 Sep 2019 18:33:51 +0100	[thread overview]
Message-ID: <20190927173409.31175-5-matthew.auld@intel.com> (raw)
In-Reply-To: <20190927173409.31175-1-matthew.auld@intel.com>

Some kernel internal objects may need to be allocated as a continuous
block, also thinking ahead the various kernel io_mapping interfaces seem
to expect it, although this is purely a limitation in the kernel
API...so perhaps something to be improved.

Signed-off-by: Matthew Auld <matthew.auld@intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: Abdiel Janulgue <abdiel.janulgue@linux.intel.com>
---
 .../gpu/drm/i915/gem/i915_gem_object_types.h  |   4 +
 drivers/gpu/drm/i915/gem/i915_gem_region.c    |  15 +-
 drivers/gpu/drm/i915/gem/i915_gem_region.h    |   3 +-
 .../gpu/drm/i915/gem/selftests/huge_pages.c   |   3 +-
 drivers/gpu/drm/i915/intel_memory_region.c    |  13 +-
 drivers/gpu/drm/i915/intel_memory_region.h    |   3 +-
 .../drm/i915/selftests/intel_memory_region.c  | 163 ++++++++++++++++++
 drivers/gpu/drm/i915/selftests/mock_region.c  |   2 +-
 8 files changed, 197 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
index d36c860c9c6f..7acd383f174f 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
@@ -117,6 +117,10 @@ struct drm_i915_gem_object {
 
 	I915_SELFTEST_DECLARE(struct list_head st_link);
 
+	unsigned long flags;
+#define I915_BO_ALLOC_CONTIGUOUS BIT(0)
+#define I915_BO_ALLOC_FLAGS (I915_BO_ALLOC_CONTIGUOUS)
+
 	/*
 	 * Is the object to be mapped as read-only to the GPU
 	 * Only honoured if hardware has relevant pte bit
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_region.c b/drivers/gpu/drm/i915/gem/i915_gem_region.c
index 5c3bfc121921..b317a5c84144 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_region.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_region.c
@@ -23,10 +23,10 @@ i915_gem_object_get_pages_buddy(struct drm_i915_gem_object *obj)
 {
 	struct intel_memory_region *mem = obj->mm.region;
 	struct list_head *blocks = &obj->mm.blocks;
-	unsigned int flags = I915_ALLOC_MIN_PAGE_SIZE;
 	resource_size_t size = obj->base.size;
 	resource_size_t prev_end;
 	struct i915_buddy_block *block;
+	unsigned int flags;
 	struct sg_table *st;
 	struct scatterlist *sg;
 	unsigned int sg_page_sizes;
@@ -42,6 +42,10 @@ i915_gem_object_get_pages_buddy(struct drm_i915_gem_object *obj)
 		return -ENOMEM;
 	}
 
+	flags = I915_ALLOC_MIN_PAGE_SIZE;
+	if (obj->flags & I915_BO_ALLOC_CONTIGUOUS)
+		flags |= I915_ALLOC_CONTIGUOUS;
+
 	ret = __intel_memory_region_get_pages_buddy(mem, size, flags, blocks);
 	if (ret)
 		goto err_free_sg;
@@ -56,7 +60,8 @@ i915_gem_object_get_pages_buddy(struct drm_i915_gem_object *obj)
 	list_for_each_entry(block, blocks, link) {
 		u64 block_size, offset;
 
-		block_size = i915_buddy_block_size(&mem->mm, block);
+		block_size = min_t(u64, size,
+				   i915_buddy_block_size(&mem->mm, block));
 		offset = i915_buddy_block_offset(block);
 
 		GEM_BUG_ON(overflows_type(block_size, sg->length));
@@ -98,10 +103,12 @@ i915_gem_object_get_pages_buddy(struct drm_i915_gem_object *obj)
 }
 
 void i915_gem_object_init_memory_region(struct drm_i915_gem_object *obj,
-					struct intel_memory_region *mem)
+					struct intel_memory_region *mem,
+					unsigned long flags)
 {
 	INIT_LIST_HEAD(&obj->mm.blocks);
 	obj->mm.region = mem;
+	obj->flags = flags;
 }
 
 void i915_gem_object_release_memory_region(struct drm_i915_gem_object *obj)
@@ -115,6 +122,8 @@ i915_gem_object_create_region(struct intel_memory_region *mem,
 {
 	struct drm_i915_gem_object *obj;
 
+	GEM_BUG_ON(flags & ~I915_BO_ALLOC_FLAGS);
+
 	if (!mem)
 		return ERR_PTR(-ENODEV);
 
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_region.h b/drivers/gpu/drm/i915/gem/i915_gem_region.h
index ebddc86d78f7..f2ff6f8bff74 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_region.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_region.h
@@ -17,7 +17,8 @@ void i915_gem_object_put_pages_buddy(struct drm_i915_gem_object *obj,
 				     struct sg_table *pages);
 
 void i915_gem_object_init_memory_region(struct drm_i915_gem_object *obj,
-					struct intel_memory_region *mem);
+					struct intel_memory_region *mem,
+					unsigned long flags);
 void i915_gem_object_release_memory_region(struct drm_i915_gem_object *obj);
 
 struct drm_i915_gem_object *
diff --git a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c
index 4e1805aaeb99..f9fbf2865782 100644
--- a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c
+++ b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c
@@ -471,7 +471,8 @@ static int igt_mock_memory_region_huge_pages(void *arg)
 		unsigned int page_size = BIT(bit);
 		resource_size_t phys;
 
-		obj = i915_gem_object_create_region(mem, page_size, 0);
+		obj = i915_gem_object_create_region(mem, page_size,
+						    I915_BO_ALLOC_CONTIGUOUS);
 		if (IS_ERR(obj)) {
 			err = PTR_ERR(obj);
 			goto out_destroy_device;
diff --git a/drivers/gpu/drm/i915/intel_memory_region.c b/drivers/gpu/drm/i915/intel_memory_region.c
index e48d5c37c4df..7a66872d9eac 100644
--- a/drivers/gpu/drm/i915/intel_memory_region.c
+++ b/drivers/gpu/drm/i915/intel_memory_region.c
@@ -47,8 +47,8 @@ __intel_memory_region_get_pages_buddy(struct intel_memory_region *mem,
 				      unsigned int flags,
 				      struct list_head *blocks)
 {
-	unsigned long n_pages = size >> ilog2(mem->mm.chunk_size);
 	unsigned int min_order = 0;
+	unsigned long n_pages;
 
 	GEM_BUG_ON(!IS_ALIGNED(size, mem->mm.chunk_size));
 	GEM_BUG_ON(!list_empty(blocks));
@@ -58,6 +58,13 @@ __intel_memory_region_get_pages_buddy(struct intel_memory_region *mem,
 			    ilog2(mem->mm.chunk_size);
 	}
 
+	if (flags & I915_ALLOC_CONTIGUOUS) {
+		size = roundup_pow_of_two(size);
+		min_order = ilog2(size) - ilog2(mem->mm.chunk_size);
+	}
+
+	n_pages = size >> ilog2(mem->mm.chunk_size);
+
 	mutex_lock(&mem->mm_lock);
 
 	do {
@@ -104,7 +111,9 @@ __intel_memory_region_get_block_buddy(struct intel_memory_region *mem,
 	int ret;
 
 	INIT_LIST_HEAD(&blocks);
-	ret = __intel_memory_region_get_pages_buddy(mem, size, 0, &blocks);
+	ret = __intel_memory_region_get_pages_buddy(mem, size,
+						    I915_ALLOC_CONTIGUOUS,
+						    &blocks);
 	if (ret)
 		return ERR_PTR(ret);
 
diff --git a/drivers/gpu/drm/i915/intel_memory_region.h b/drivers/gpu/drm/i915/intel_memory_region.h
index ae1ce298bcd1..1dad51b2fc96 100644
--- a/drivers/gpu/drm/i915/intel_memory_region.h
+++ b/drivers/gpu/drm/i915/intel_memory_region.h
@@ -17,7 +17,8 @@ struct drm_i915_gem_object;
 struct intel_memory_region;
 struct sg_table;
 
-#define I915_ALLOC_MIN_PAGE_SIZE   BIT(0)
+#define I915_ALLOC_MIN_PAGE_SIZE  BIT(0)
+#define I915_ALLOC_CONTIGUOUS     BIT(1)
 
 struct intel_memory_region_ops {
 	unsigned int flags;
diff --git a/drivers/gpu/drm/i915/selftests/intel_memory_region.c b/drivers/gpu/drm/i915/selftests/intel_memory_region.c
index 54f9a624b4e1..c43d00ec38ea 100644
--- a/drivers/gpu/drm/i915/selftests/intel_memory_region.c
+++ b/drivers/gpu/drm/i915/selftests/intel_memory_region.c
@@ -13,6 +13,7 @@
 
 #include "gem/i915_gem_region.h"
 #include "gem/selftests/mock_context.h"
+#include "selftests/i915_random.h"
 
 static void close_objects(struct list_head *objects)
 {
@@ -89,10 +90,172 @@ static int igt_mock_fill(void *arg)
 	return err;
 }
 
+static struct drm_i915_gem_object *
+igt_object_create(struct intel_memory_region *mem,
+		  struct list_head *objects,
+		  u64 size,
+		  unsigned int flags)
+{
+	struct drm_i915_gem_object *obj;
+	int err;
+
+	obj = i915_gem_object_create_region(mem, size, flags);
+	if (IS_ERR(obj))
+		return obj;
+
+	err = i915_gem_object_pin_pages(obj);
+	if (err)
+		goto put;
+
+	list_add(&obj->st_link, objects);
+	return obj;
+
+put:
+	i915_gem_object_put(obj);
+	return ERR_PTR(err);
+}
+
+void igt_object_release(struct drm_i915_gem_object *obj)
+{
+	i915_gem_object_unpin_pages(obj);
+	__i915_gem_object_put_pages(obj, I915_MM_NORMAL);
+	i915_gem_object_put(obj);
+	list_del(&obj->st_link);
+}
+
+static int igt_mock_continuous(void *arg)
+{
+	struct intel_memory_region *mem = arg;
+	struct drm_i915_gem_object *obj;
+	unsigned long n_objects;
+	LIST_HEAD(objects);
+	LIST_HEAD(holes);
+	I915_RND_STATE(prng);
+	resource_size_t target;
+	resource_size_t total;
+	resource_size_t min;
+	int err = 0;
+
+	total = resource_size(&mem->region);
+
+	/* Min size */
+	obj = igt_object_create(mem, &objects, mem->mm.chunk_size,
+				I915_BO_ALLOC_CONTIGUOUS);
+	if (IS_ERR(obj))
+		return PTR_ERR(obj);
+
+	if (obj->mm.pages->nents != 1) {
+		pr_err("%s min object spans multiple sg entries\n", __func__);
+		err = -EINVAL;
+		goto err_close_objects;
+	}
+
+	igt_object_release(obj);
+
+	/* Max size */
+	obj = igt_object_create(mem, &objects, total, I915_BO_ALLOC_CONTIGUOUS);
+	if (IS_ERR(obj))
+		return PTR_ERR(obj);
+
+	if (obj->mm.pages->nents != 1) {
+		pr_err("%s max object spans multiple sg entries\n", __func__);
+		err = -EINVAL;
+		goto err_close_objects;
+	}
+
+	igt_object_release(obj);
+
+	/* Internal fragmentation should not bleed into the object size */
+	target = round_up(prandom_u32_state(&prng) % total, PAGE_SIZE);
+	target = max_t(u64, PAGE_SIZE, target);
+
+	obj = igt_object_create(mem, &objects, target,
+				I915_BO_ALLOC_CONTIGUOUS);
+	if (IS_ERR(obj))
+		return PTR_ERR(obj);
+
+	if (obj->base.size != target) {
+		pr_err("%s obj->base.size(%llx) != target(%llx)\n", __func__,
+		       (u64)obj->base.size, (u64)target);
+		err = -EINVAL;
+		goto err_close_objects;
+	}
+
+	if (obj->mm.pages->nents != 1) {
+		pr_err("%s object spans multiple sg entries\n", __func__);
+		err = -EINVAL;
+		goto err_close_objects;
+	}
+
+	igt_object_release(obj);
+
+	/*
+	 * Try to fragment the address space, such that half of it is free, but
+	 * the max contiguous block size is SZ_64K.
+	 */
+
+	target = SZ_64K;
+	n_objects = div64_u64(total, target);
+
+	while (n_objects--) {
+		struct list_head *list;
+
+		if (n_objects % 2)
+			list = &holes;
+		else
+			list = &objects;
+
+		obj = igt_object_create(mem, list, target,
+					I915_BO_ALLOC_CONTIGUOUS);
+		if (IS_ERR(obj)) {
+			err = PTR_ERR(obj);
+			goto err_close_objects;
+		}
+	}
+
+	close_objects(&holes);
+
+	min = target;
+	target = total >> 1;
+
+	/* Make sure we can still allocate all the fragmented space */
+	obj = igt_object_create(mem, &objects, target, 0);
+	if (IS_ERR(obj))
+		return PTR_ERR(obj);
+
+	igt_object_release(obj);
+
+	/*
+	 * Even though we have enough free space, we don't have a big enough
+	 * contiguous block. Make sure that holds true.
+	 */
+
+	do {
+		bool should_fail = target > min;
+
+		obj = igt_object_create(mem, &objects, target,
+					I915_BO_ALLOC_CONTIGUOUS);
+		if (should_fail != IS_ERR(obj)) {
+			pr_err("%s target allocation(%llx) mismatch\n",
+			       __func__, (u64)target);
+			err = -EINVAL;
+			goto err_close_objects;
+		}
+
+		target >>= 1;
+	} while (target >= mem->mm.chunk_size);
+
+err_close_objects:
+	list_splice_tail(&holes, &objects);
+	close_objects(&objects);
+	return err;
+}
+
 int intel_memory_region_mock_selftests(void)
 {
 	static const struct i915_subtest tests[] = {
 		SUBTEST(igt_mock_fill),
+		SUBTEST(igt_mock_continuous),
 	};
 	struct intel_memory_region *mem;
 	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
index 0e9a575ede3b..7b0c99ddc2d5 100644
--- a/drivers/gpu/drm/i915/selftests/mock_region.c
+++ b/drivers/gpu/drm/i915/selftests/mock_region.c
@@ -36,7 +36,7 @@ mock_object_create(struct intel_memory_region *mem,
 
 	i915_gem_object_set_cache_coherency(obj, I915_CACHE_NONE);
 
-	i915_gem_object_init_memory_region(obj, mem);
+	i915_gem_object_init_memory_region(obj, mem, flags);
 
 	return obj;
 }
-- 
2.20.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

  parent reply	other threads:[~2019-09-27 17:34 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-09-27 17:33 [PATCH 00/22] LMEM basics Matthew Auld
2019-09-27 17:33 ` [PATCH 01/22] drm/i915: check for kernel_context Matthew Auld
2019-09-27 17:37   ` Chris Wilson
2019-09-27 17:33 ` [PATCH 02/22] drm/i915: simplify i915_gem_init_early Matthew Auld
2019-09-27 17:39   ` Chris Wilson
2019-09-27 17:33 ` [PATCH 03/22] drm/i915: introduce intel_memory_region Matthew Auld
2019-09-27 18:08   ` Chris Wilson
2019-09-27 18:21   ` Chris Wilson
2019-09-27 18:24   ` Chris Wilson
2019-09-27 18:25     ` Chris Wilson
2019-09-27 20:27   ` Chris Wilson
2019-09-27 20:30   ` Chris Wilson
2019-09-27 17:33 ` Matthew Auld [this message]
2019-09-27 18:35   ` [PATCH 04/22] drm/i915/region: support continuous allocations Chris Wilson
2019-09-27 18:46   ` Ruhl, Michael J
2019-09-27 17:33 ` [PATCH 05/22] drm/i915/region: support volatile objects Matthew Auld
2019-09-27 17:33 ` [PATCH 06/22] drm/i915: Add memory region information to device_info Matthew Auld
2019-09-27 17:33 ` [PATCH 07/22] drm/i915: support creating LMEM objects Matthew Auld
2019-09-27 18:45   ` Chris Wilson
2019-09-27 17:33 ` [PATCH 08/22] drm/i915: setup io-mapping for LMEM Matthew Auld
2019-09-27 17:33 ` [PATCH 09/22] drm/i915/lmem: support kernel mapping Matthew Auld
2019-09-27 19:24   ` Chris Wilson
2019-09-27 20:39   ` Chris Wilson
2019-09-27 17:33 ` [PATCH 10/22] drm/i915/selftests: add write-dword test for LMEM Matthew Auld
2019-09-27 19:27   ` Chris Wilson
2019-09-27 20:42   ` Chris Wilson
2019-09-30  9:58     ` Matthew Auld
2019-09-30 10:46       ` Chris Wilson
2019-09-27 17:33 ` [PATCH 11/22] drm/i915/selftest: extend coverage to include LMEM huge-pages Matthew Auld
2019-09-27 17:33 ` [PATCH 12/22] drm/i915: enumerate and init each supported region Matthew Auld
2019-09-27 20:44   ` Chris Wilson
2019-09-27 17:34 ` [PATCH 13/22] drm/i915: treat shmem as a region Matthew Auld
2019-09-27 17:34 ` [PATCH 14/22] drm/i915: treat stolen " Matthew Auld
2019-09-27 19:30   ` Chris Wilson
2019-09-27 17:34 ` [PATCH 15/22] drm/i915: define HAS_MAPPABLE_APERTURE Matthew Auld
2019-09-27 17:34 ` [PATCH 16/22] drm/i915: do not map aperture if it is not available Matthew Auld
2019-09-27 17:34 ` [PATCH 17/22] drm/i915: set num_fence_regs to 0 if there is no aperture Matthew Auld
2019-09-27 20:49   ` Chris Wilson
2019-09-27 17:34 ` [PATCH 18/22] drm/i915/selftests: check for missing aperture Matthew Auld
2019-09-27 20:51   ` Chris Wilson
2019-09-27 17:34 ` [PATCH 19/22] drm/i915: error capture with no ggtt slot Matthew Auld
2019-09-27 17:52   ` Chris Wilson
2019-09-27 17:34 ` [PATCH 20/22] drm/i915: Don't try to place HWS in non-existing mappable region Matthew Auld
2019-09-27 17:34 ` [PATCH 21/22] drm/i915: check for missing aperture in GTT pread/pwrite paths Matthew Auld
2019-09-27 17:57   ` Chris Wilson
2019-09-27 17:34 ` [PATCH 22/22] HAX drm/i915: add the fake lmem region Matthew Auld
2019-09-27 18:29 ` ✗ Fi.CI.CHECKPATCH: warning for LMEM basics Patchwork
2019-09-27 18:39 ` ✗ Fi.CI.SPARSE: " Patchwork
2019-09-27 18:51 ` ✓ Fi.CI.BAT: success " Patchwork
2019-09-28  9:47 ` ✗ Fi.CI.IGT: failure " Patchwork

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190927173409.31175-5-matthew.auld@intel.com \
    --to=matthew.auld@intel.com \
    --cc=daniel.vetter@ffwll.ch \
    --cc=intel-gfx@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.