mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-09-18 23:09:29 +02:00
drm/tests/gpu_buddy: fix interleaving in buffer clearance test
The resume clearance test skipped every other allocation, expecting an
interleaved clear/dirty layout. But the buddy allocator hands out blocks
contiguously, so this just allocated half the pages in one chunk and never
exercised gpu_buddy_reset_clear()'s force-merge of opposite-state buddies.
Allocate all pages into two lists instead and free one cleared, one dirty,
to build a truly interleaved pattern.
v2: Use for loops instead of do-while for the allocation loops (Jani Nikula)
Fixes: e3335ccbf4 ("drm/tests/gpu_buddy: add a new test case for buffer clearance during resume")
Reported-by: Sashiko-bot <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/patchset/20260721114236.507578-1-Arunpravin.PaneerSelvam@amd.com?part=1
Cc: Matthew Auld <matthew.auld@intel.com>
Cc: Christian König <christian.koenig@amd.com>
Assisted-by: GitHub_Copilot:claude-opus-4.8
Signed-off-by: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam@amd.com>
Reviewed-by: Matthew Auld <matthew.auld@intel.com>
Link: https://patch.msgid.link/20260803065656.2960810-1-Arunpravin.PaneerSelvam@amd.com
This commit is contained in:
@@ -1004,42 +1004,51 @@ static void gpu_test_buddy_alloc_clear(struct kunit *test)
|
||||
gpu_buddy_fini(&mm);
|
||||
|
||||
/*
|
||||
* Using a non-power-of-two mm size, allocate alternating blocks of 4KiB in an
|
||||
* even sequence and free them as cleared. All blocks should be marked as
|
||||
* dirty and the split blocks should be merged back to their original
|
||||
* size when the blocks clear reset function is called.
|
||||
* Using a non-power-of-two mm size, allocate all 4KiB blocks and split
|
||||
* them across two alternating lists, then free one list as cleared and
|
||||
* the other as dirty. This interleaves cleared and dirty blocks so that
|
||||
* neighbouring buddies cannot be merged, fragmenting the address space.
|
||||
* After gpu_buddy_reset_clear(false) every block should be marked dirty
|
||||
* and the split blocks should be merged back to their original size, so
|
||||
* clear_avail must drop to 0.
|
||||
*/
|
||||
KUNIT_EXPECT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps));
|
||||
KUNIT_EXPECT_EQ(test, mm.max_order, max_order);
|
||||
|
||||
i = 0;
|
||||
n_pages = mm_size / ps;
|
||||
do {
|
||||
if (i % 2 == 0)
|
||||
KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size,
|
||||
ps, ps, &allocated, 0),
|
||||
"buddy_alloc hit an error size=%lu\n", ps);
|
||||
} while (++i < n_pages);
|
||||
for (i = 0; i < n_pages; i++) {
|
||||
struct list_head *list = (i % 2) ? &clean : &dirty;
|
||||
|
||||
gpu_buddy_free_list(&mm, &allocated, GPU_BUDDY_CLEARED);
|
||||
KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size,
|
||||
ps, ps, list, 0),
|
||||
"buddy_alloc hit an error size=%lu\n", ps);
|
||||
}
|
||||
|
||||
gpu_buddy_free_list(&mm, &clean, GPU_BUDDY_CLEARED);
|
||||
gpu_buddy_free_list(&mm, &dirty, 0);
|
||||
gpu_buddy_reset_clear(&mm, false);
|
||||
KUNIT_EXPECT_EQ(test, mm.clear_avail, 0);
|
||||
gpu_buddy_fini(&mm);
|
||||
|
||||
/*
|
||||
* Using a non-power-of-two mm size, allocate alternating blocks of 4KiB in an
|
||||
* odd sequence and free them as cleared. All blocks should be marked as
|
||||
* cleared and the split blocks should be merged back to their original
|
||||
* size when the blocks clear reset function is called.
|
||||
* Repeat the same fragmented setup, but this time call
|
||||
* gpu_buddy_reset_clear(true). Every block should be marked cleared and
|
||||
* the split blocks should be merged back to their original size, so the
|
||||
* whole address space (clear_avail) must equal mm_size.
|
||||
*/
|
||||
i = 0;
|
||||
do {
|
||||
if (i % 2 != 0)
|
||||
KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size,
|
||||
ps, ps, &allocated, 0),
|
||||
"buddy_alloc hit an error size=%lu\n", ps);
|
||||
} while (++i < n_pages);
|
||||
KUNIT_EXPECT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps));
|
||||
KUNIT_EXPECT_EQ(test, mm.max_order, max_order);
|
||||
|
||||
gpu_buddy_free_list(&mm, &allocated, GPU_BUDDY_CLEARED);
|
||||
for (i = 0; i < n_pages; i++) {
|
||||
struct list_head *list = (i % 2) ? &clean : &dirty;
|
||||
|
||||
KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size,
|
||||
ps, ps, list, 0),
|
||||
"buddy_alloc hit an error size=%lu\n", ps);
|
||||
}
|
||||
|
||||
gpu_buddy_free_list(&mm, &clean, GPU_BUDDY_CLEARED);
|
||||
gpu_buddy_free_list(&mm, &dirty, 0);
|
||||
gpu_buddy_reset_clear(&mm, true);
|
||||
KUNIT_EXPECT_EQ(test, mm.clear_avail, mm_size);
|
||||
gpu_buddy_fini(&mm);
|
||||
|
||||
Reference in New Issue
Block a user