drm/i915/buddy: document the unused header bits
authorMatthew Auld <matthew.auld@intel.com>
Tue, 26 Jan 2021 10:30:19 +0000 (10:30 +0000)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Wed, 24 Mar 2021 18:30:35 +0000 (19:30 +0100)
The largest possible order is (63-PAGE_SHIFT), given that our min chunk
size is PAGE_SIZE. With that we should only need at most 6 bits to
represent all possible orders, giving us back 4 bits for other potential
uses.  Include a simple selftest to verify this.

Signed-off-by: Matthew Auld <matthew.auld@intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: https://patchwork.freedesktop.org/patch/msgid/20210126103019.177622-1-matthew.auld@intel.com
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_buddy.c
drivers/gpu/drm/i915/i915_buddy.h
drivers/gpu/drm/i915/selftests/i915_buddy.c

index 20babbd..3a2f6ee 100644 (file)
@@ -48,6 +48,8 @@ static struct i915_buddy_block *i915_block_alloc(struct i915_buddy_block *parent
 {
        struct i915_buddy_block *block;
 
+       GEM_BUG_ON(order > I915_BUDDY_MAX_ORDER);
+
        block = kmem_cache_zalloc(global.slab_blocks, GFP_KERNEL);
        if (!block)
                return NULL;
@@ -56,6 +58,7 @@ static struct i915_buddy_block *i915_block_alloc(struct i915_buddy_block *parent
        block->header |= order;
        block->parent = parent;
 
+       GEM_BUG_ON(block->header & I915_BUDDY_HEADER_UNUSED);
        return block;
 }
 
index ed41f35..9ce5200 100644 (file)
@@ -15,7 +15,9 @@ struct i915_buddy_block {
 #define   I915_BUDDY_ALLOCATED    (1 << 10)
 #define   I915_BUDDY_FREE         (2 << 10)
 #define   I915_BUDDY_SPLIT        (3 << 10)
-#define I915_BUDDY_HEADER_ORDER  GENMASK_ULL(9, 0)
+/* Free to be used, if needed in the future */
+#define I915_BUDDY_HEADER_UNUSED GENMASK_ULL(9, 6)
+#define I915_BUDDY_HEADER_ORDER  GENMASK_ULL(5, 0)
        u64 header;
 
        struct i915_buddy_block *left;
@@ -34,7 +36,8 @@ struct i915_buddy_block {
        struct list_head tmp_link;
 };
 
-#define I915_BUDDY_MAX_ORDER  I915_BUDDY_HEADER_ORDER
+/* Order-zero must be at least PAGE_SIZE */
+#define I915_BUDDY_MAX_ORDER (63 - PAGE_SHIFT)
 
 /*
  * Binary Buddy System.
index 632b912..f0f5c4d 100644 (file)
@@ -727,6 +727,53 @@ err_fini:
        return err;
 }
 
+static int igt_buddy_alloc_limit(void *arg)
+{
+       struct i915_buddy_block *block;
+       struct i915_buddy_mm mm;
+       const u64 size = U64_MAX;
+       int err;
+
+       err = i915_buddy_init(&mm, size, PAGE_SIZE);
+       if (err)
+               return err;
+
+       if (mm.max_order != I915_BUDDY_MAX_ORDER) {
+               pr_err("mm.max_order(%d) != %d\n",
+                      mm.max_order, I915_BUDDY_MAX_ORDER);
+               err = -EINVAL;
+               goto out_fini;
+       }
+
+       block = i915_buddy_alloc(&mm, mm.max_order);
+       if (IS_ERR(block)) {
+               err = PTR_ERR(block);
+               goto out_fini;
+       }
+
+       if (i915_buddy_block_order(block) != mm.max_order) {
+               pr_err("block order(%d) != %d\n",
+                      i915_buddy_block_order(block), mm.max_order);
+               err = -EINVAL;
+               goto out_free;
+       }
+
+       if (i915_buddy_block_size(&mm, block) !=
+           BIT_ULL(mm.max_order) * PAGE_SIZE) {
+               pr_err("block size(%llu) != %llu\n",
+                      i915_buddy_block_size(&mm, block),
+                      BIT_ULL(mm.max_order) * PAGE_SIZE);
+               err = -EINVAL;
+               goto out_free;
+       }
+
+out_free:
+       i915_buddy_free(&mm, block);
+out_fini:
+       i915_buddy_fini(&mm);
+       return err;
+}
+
 int i915_buddy_mock_selftests(void)
 {
        static const struct i915_subtest tests[] = {
@@ -735,6 +782,7 @@ int i915_buddy_mock_selftests(void)
                SUBTEST(igt_buddy_alloc_pathological),
                SUBTEST(igt_buddy_alloc_smoke),
                SUBTEST(igt_buddy_alloc_range),
+               SUBTEST(igt_buddy_alloc_limit),
        };
 
        return i915_subtests(tests, NULL);