summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2024-05-16 08:44:19 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2024-05-16 08:44:19 -0700
commit972a2543e3dd87f7310d65944b857631b4290e12 (patch)
tree5010631871e18915eb070ef90932ad0479066864 /drivers/gpu
parent3c999d1ae3c75991902a1a7dad0cb62c2a3008b4 (diff)
parent431c590c3ab0469dfedad3a832fe73556396ee52 (diff)
Merge tag 'drm-next-2024-05-16' of https://gitlab.freedesktop.org/drm/kernel
Pull drm fix from Dave Airlie: - fix breakage in buddy allocator * tag 'drm-next-2024-05-16' of https://gitlab.freedesktop.org/drm/kernel: drm/tests: Add a unit test for range bias allocation drm/buddy: Fix the range bias clear memory allocation issue
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/drm_buddy.c3
-rw-r--r--drivers/gpu/drm/tests/drm_buddy_test.c36
2 files changed, 37 insertions, 2 deletions
diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/drm/drm_buddy.c
index 284ebae71cc4..1daf778cf6fa 100644
--- a/drivers/gpu/drm/drm_buddy.c
+++ b/drivers/gpu/drm/drm_buddy.c
@@ -249,6 +249,7 @@ int drm_buddy_init(struct drm_buddy *mm, u64 size, u64 chunk_size)
mm->size = size;
mm->avail = size;
+ mm->clear_avail = 0;
mm->chunk_size = chunk_size;
mm->max_order = ilog2(size) - ilog2(chunk_size);
@@ -574,7 +575,7 @@ __drm_buddy_alloc_range_bias(struct drm_buddy *mm,
block = __alloc_range_bias(mm, start, end, order,
flags, fallback);
- if (IS_ERR(block) && mm->clear_avail)
+ if (IS_ERR(block))
return __alloc_range_bias(mm, start, end, order,
flags, !fallback);
diff --git a/drivers/gpu/drm/tests/drm_buddy_test.c b/drivers/gpu/drm/tests/drm_buddy_test.c
index e3b50e240d36..b3be68b03610 100644
--- a/drivers/gpu/drm/tests/drm_buddy_test.c
+++ b/drivers/gpu/drm/tests/drm_buddy_test.c
@@ -23,9 +23,11 @@ static inline u64 get_size(int order, u64 chunk_size)
static void drm_test_buddy_alloc_range_bias(struct kunit *test)
{
- u32 mm_size, ps, bias_size, bias_start, bias_end, bias_rem;
+ u32 mm_size, size, ps, bias_size, bias_start, bias_end, bias_rem;
DRM_RND_STATE(prng, random_seed);
unsigned int i, count, *order;
+ struct drm_buddy_block *block;
+ unsigned long flags;
struct drm_buddy mm;
LIST_HEAD(allocated);
@@ -222,6 +224,38 @@ static void drm_test_buddy_alloc_range_bias(struct kunit *test)
drm_buddy_free_list(&mm, &allocated, 0);
drm_buddy_fini(&mm);
+
+ /*
+ * Allocate cleared blocks in the bias range when the DRM buddy's clear avail is
+ * zero. This will validate the bias range allocation in scenarios like system boot
+ * when no cleared blocks are available and exercise the fallback path too. The resulting
+ * blocks should always be dirty.
+ */
+
+ KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_init(&mm, mm_size, ps),
+ "buddy_init failed\n");
+
+ bias_start = round_up(prandom_u32_state(&prng) % (mm_size - ps), ps);
+ bias_end = round_up(bias_start + prandom_u32_state(&prng) % (mm_size - bias_start), ps);
+ bias_end = max(bias_end, bias_start + ps);
+ bias_rem = bias_end - bias_start;
+
+ flags = DRM_BUDDY_CLEAR_ALLOCATION | DRM_BUDDY_RANGE_ALLOCATION;
+ size = max(round_up(prandom_u32_state(&prng) % bias_rem, ps), ps);
+
+ KUNIT_ASSERT_FALSE_MSG(test,
+ drm_buddy_alloc_blocks(&mm, bias_start,
+ bias_end, size, ps,
+ &allocated,
+ flags),
+ "buddy_alloc failed with bias(%x-%x), size=%u, ps=%u\n",
+ bias_start, bias_end, size, ps);
+
+ list_for_each_entry(block, &allocated, link)
+ KUNIT_EXPECT_EQ(test, drm_buddy_block_is_clear(block), false);
+
+ drm_buddy_free_list(&mm, &allocated, 0);
+ drm_buddy_fini(&mm);
}
static void drm_test_buddy_alloc_clear(struct kunit *test)