diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2024-05-16 08:44:19 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2024-05-16 08:44:19 -0700 |
commit | 972a2543e3dd87f7310d65944b857631b4290e12 (patch) | |
tree | 5010631871e18915eb070ef90932ad0479066864 /drivers/gpu | |
parent | 3c999d1ae3c75991902a1a7dad0cb62c2a3008b4 (diff) | |
parent | 431c590c3ab0469dfedad3a832fe73556396ee52 (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.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/tests/drm_buddy_test.c | 36 |
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) |