mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 16:53:20 -04:00
drm/xe/tests: add live KUnit coverage for BO page-size allocation modes
Add live KUnit coverage for the debug-controlled BO
page-size allocation modes.
The new tests cover forced 2M mode, forced 1G mode,
and mixed mode. They verify that user BO creation applies
the expected NEEDS_* flags, that no unexpected page-size flags are
added in the forced modes, that BO size is rounded as expected, and
that page_alignment matches the selected leaf size.
The mixed-mode test does not assume a strict per-allocation rotation
sequence, since the device-global mixed-mode index may be perturbed by
concurrent BO creation on a live system. Instead,
it validates that each allocation results in
one valid mixed-mode page-size outcome.
Treat transient VRAM allocation failures as skipped test cases so the
tests can run in varying live environments without producing false
failures.
v3
- address review comments
- rework mixed-mode test to avoid assuming strict rotation order
- reword commit message
v4
- skip VRAM-targeted live tests on non-dGFX devices
v5
- advance the mixed-mode index in the test
v6
- Gaurd kunit tests under CONFIG_DRM_XE_DEBUG_PAGE_SIZE
v9
- consider XE_VRAM_FLAGS_NEED64K in mixed mode for certain
platoform min alignment expectations.
Signed-off-by: Nareshkumar Gollakoti <naresh.kumar.g@intel.com>
Reviewed-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
Link: https://patch.msgid.link/20260729121843.1255891-7-naresh.kumar.g@intel.com
Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
This commit is contained in:
committed by
Himal Prasad Ghimiray
parent
41a74ed31f
commit
60693b580a
@@ -22,6 +22,231 @@
|
||||
#include "xe_pci.h"
|
||||
#include "xe_pm.h"
|
||||
|
||||
#ifdef CONFIG_DRM_XE_DEBUG_PAGE_SIZE
|
||||
struct page_size_alloc_saved {
|
||||
enum xe_page_size_alloc_ctrl_mode mode;
|
||||
u32 cur_index;
|
||||
};
|
||||
|
||||
/* Caller must hold xe->page_size_alloc_ctrl.lock. */
|
||||
static void page_size_alloc_save(struct xe_device *xe,
|
||||
struct page_size_alloc_saved *s)
|
||||
{
|
||||
s->mode = xe->page_size_alloc_ctrl.mode;
|
||||
s->cur_index = xe->page_size_alloc_ctrl.cur_index;
|
||||
}
|
||||
|
||||
static void page_size_alloc_restore(struct xe_device *xe,
|
||||
const struct page_size_alloc_saved *s)
|
||||
{
|
||||
mutex_lock(&xe->page_size_alloc_ctrl.lock);
|
||||
xe->page_size_alloc_ctrl.mode = s->mode;
|
||||
xe->page_size_alloc_ctrl.cur_index = s->cur_index;
|
||||
mutex_unlock(&xe->page_size_alloc_ctrl.lock);
|
||||
}
|
||||
|
||||
/* Expected properties for a forced page-size allocation mode. */
|
||||
struct leaf_info {
|
||||
u64 leaf;
|
||||
u64 alloc_size;
|
||||
u32 flag;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
static const struct leaf_info leaf_2m = {
|
||||
.leaf = SZ_2M,
|
||||
.alloc_size = SZ_2M - PAGE_SIZE,
|
||||
.flag = XE_BO_FLAG_NEEDS_2M,
|
||||
.name = "2M",
|
||||
};
|
||||
|
||||
static const struct leaf_info leaf_1g = {
|
||||
.leaf = SZ_1G,
|
||||
.alloc_size = SZ_1G - PAGE_SIZE,
|
||||
.flag = XE_BO_FLAG_NEEDS_1G,
|
||||
.name = "1G",
|
||||
};
|
||||
|
||||
static void run_only_leaf(struct kunit *test,
|
||||
enum xe_page_size_alloc_ctrl_mode mode,
|
||||
const struct leaf_info *li)
|
||||
{
|
||||
struct xe_device *xe = test->priv;
|
||||
struct page_size_alloc_saved saved;
|
||||
struct xe_bo *bo;
|
||||
struct ttm_buffer_object *ttm_bo;
|
||||
u32 other_flags;
|
||||
|
||||
if (!IS_DGFX(xe)) {
|
||||
kunit_skip(test, "requires dGFX VRAM");
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_lock(&xe->page_size_alloc_ctrl.lock);
|
||||
page_size_alloc_save(xe, &saved);
|
||||
xe->page_size_alloc_ctrl.mode = mode;
|
||||
mutex_unlock(&xe->page_size_alloc_ctrl.lock);
|
||||
|
||||
bo = xe_bo_create_user(xe, NULL, li->alloc_size,
|
||||
DRM_XE_GEM_CPU_CACHING_WC,
|
||||
XE_BO_FLAG_VRAM0, NULL);
|
||||
if (IS_ERR(bo)) {
|
||||
page_size_alloc_restore(xe, &saved);
|
||||
if (PTR_ERR(bo) == -ENOSPC) {
|
||||
kunit_skip(test,
|
||||
"no contiguous %s VRAM available right now",
|
||||
li->name);
|
||||
return;
|
||||
}
|
||||
|
||||
KUNIT_FAIL(test, "%s BO alloc failed: %pe", li->name, bo);
|
||||
return;
|
||||
}
|
||||
|
||||
ttm_bo = &bo->ttm;
|
||||
|
||||
/* 1) The mode added the right NEEDS_* flag. */
|
||||
KUNIT_EXPECT_TRUE_MSG(test, bo->flags & li->flag,
|
||||
"%s: flag missing, flags=0x%x",
|
||||
li->name, bo->flags);
|
||||
|
||||
/* 2) No other NEEDS_* flags accidentally tagged on. */
|
||||
other_flags = (XE_BO_FLAG_NEEDS_64K |
|
||||
XE_BO_FLAG_NEEDS_2M |
|
||||
XE_BO_FLAG_NEEDS_1G) & ~li->flag;
|
||||
KUNIT_EXPECT_FALSE_MSG(test, bo->flags & other_flags,
|
||||
"%s: stray flags=0x%x",
|
||||
li->name, bo->flags);
|
||||
/* 3) BO size was rounded up to the expected leaf size. */
|
||||
KUNIT_EXPECT_EQ_MSG(test, xe_bo_size(bo), li->leaf,
|
||||
"%s: bo size=%llu expected=%llu",
|
||||
li->name,
|
||||
(u64)xe_bo_size(bo),
|
||||
(u64)li->leaf);
|
||||
/*
|
||||
* 4) Allocator honored the requested alignment.
|
||||
* ttm_bo->page_alignment is stored in PAGE_SIZE units, so compare against
|
||||
* the expected leaf size converted with >> PAGE_SHIFT.
|
||||
*/
|
||||
KUNIT_EXPECT_EQ_MSG(test, ttm_bo->page_alignment,
|
||||
li->leaf >> PAGE_SHIFT,
|
||||
"%s: page_alignment=%u pages expected=%llu pages",
|
||||
li->name, ttm_bo->page_alignment,
|
||||
(u64)(li->leaf >> PAGE_SHIFT));
|
||||
|
||||
xe_bo_put(bo);
|
||||
page_size_alloc_restore(xe, &saved);
|
||||
}
|
||||
|
||||
static void xe_bo_page_size_alloc_only_2m(struct kunit *test)
|
||||
{
|
||||
run_only_leaf(test, XE_PAGE_SIZE_ALLOC_CTRL_MODE_ONLY_2M, &leaf_2m);
|
||||
}
|
||||
|
||||
static void xe_bo_page_size_alloc_only_1g(struct kunit *test)
|
||||
{
|
||||
run_only_leaf(test, XE_PAGE_SIZE_ALLOC_CTRL_MODE_ONLY_1G, &leaf_1g);
|
||||
}
|
||||
|
||||
static void xe_bo_page_size_alloc_mixed_bos(struct kunit *test)
|
||||
{
|
||||
struct xe_device *xe = test->priv;
|
||||
struct page_size_alloc_saved saved;
|
||||
struct xe_bo *bo;
|
||||
struct ttm_buffer_object *ttm_bo;
|
||||
u32 all_flags = XE_BO_FLAG_NEEDS_64K | XE_BO_FLAG_NEEDS_2M |
|
||||
XE_BO_FLAG_NEEDS_1G;
|
||||
u32 flags;
|
||||
u64 expected_align;
|
||||
int i;
|
||||
const int n = 4;
|
||||
|
||||
if (!IS_DGFX(xe)) {
|
||||
kunit_skip(test, "requires dGFX VRAM");
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_lock(&xe->page_size_alloc_ctrl.lock);
|
||||
page_size_alloc_save(xe, &saved);
|
||||
mutex_unlock(&xe->page_size_alloc_ctrl.lock);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
mutex_lock(&xe->page_size_alloc_ctrl.lock);
|
||||
xe->page_size_alloc_ctrl.mode = XE_PAGE_SIZE_ALLOC_CTRL_MODE_MIXED;
|
||||
xe->page_size_alloc_ctrl.cur_index = i;
|
||||
mutex_unlock(&xe->page_size_alloc_ctrl.lock);
|
||||
/*
|
||||
* Request a size valid for any mixed-mode slot. Since cur_index is
|
||||
* device-global and may be perturbed by concurrent allocations on
|
||||
* a live system, do not assume this iteration will see a specific
|
||||
* slot.
|
||||
*/
|
||||
bo = xe_bo_create_user(xe, NULL, SZ_1G,
|
||||
DRM_XE_GEM_CPU_CACHING_WC,
|
||||
XE_BO_FLAG_VRAM0, NULL);
|
||||
if (IS_ERR(bo)) {
|
||||
int err = PTR_ERR(bo);
|
||||
|
||||
page_size_alloc_restore(xe, &saved);
|
||||
if (err == -ENOSPC) {
|
||||
kunit_skip(test,
|
||||
"mixed mode BO allocation unavailable: %d",
|
||||
err);
|
||||
return;
|
||||
}
|
||||
KUNIT_FAIL(test, "iter=%d alloc failed: %pe", i, bo);
|
||||
return;
|
||||
}
|
||||
|
||||
ttm_bo = &bo->ttm;
|
||||
flags = bo->flags & all_flags;
|
||||
/*
|
||||
* Mixed mode may result in:
|
||||
* 0-> default platform VRAM alignment
|
||||
* XE_BO_FLAG_NEEDS_64K
|
||||
* XE_BO_FLAG_NEEDS_2M
|
||||
* XE_BO_FLAG_NEEDS_1G
|
||||
* Any other combination is invalid.
|
||||
*/
|
||||
if (flags == 0) {
|
||||
expected_align = SZ_4K;
|
||||
if (xe->info.vram_flags & XE_VRAM_FLAGS_NEED64K)
|
||||
expected_align = SZ_64K;
|
||||
} else if (flags == XE_BO_FLAG_NEEDS_64K) {
|
||||
expected_align = SZ_64K;
|
||||
} else if (flags == XE_BO_FLAG_NEEDS_2M) {
|
||||
expected_align = SZ_2M;
|
||||
} else if (flags == XE_BO_FLAG_NEEDS_1G) {
|
||||
expected_align = SZ_1G;
|
||||
} else {
|
||||
KUNIT_FAIL(test,
|
||||
"iter=%d invalid mixed-mode flags: 0x%x",
|
||||
i, flags);
|
||||
xe_bo_put(bo);
|
||||
page_size_alloc_restore(xe, &saved);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* BO size should remain valid for the selected mode. Since the
|
||||
* request is SZ_1G, it should remain unchanged regardless of the
|
||||
* selected page-size policy.
|
||||
*/
|
||||
KUNIT_EXPECT_EQ_MSG(test, xe_bo_size(bo), (u64)SZ_1G,
|
||||
"iter=%d size=%llu expected=%llu",
|
||||
i,
|
||||
(u64)xe_bo_size(bo),
|
||||
(u64)SZ_1G);
|
||||
KUNIT_EXPECT_EQ_MSG(test, ttm_bo->page_alignment,
|
||||
expected_align >> PAGE_SHIFT,
|
||||
"iter=%d flags=0x%x page_alignment=%u pages expected=%llu pages",
|
||||
i, flags, ttm_bo->page_alignment,
|
||||
(u64)(expected_align >> PAGE_SHIFT));
|
||||
xe_bo_put(bo);
|
||||
}
|
||||
page_size_alloc_restore(xe, &saved);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int ccs_test_migrate(struct xe_tile *tile, struct xe_bo *bo,
|
||||
bool clear, u64 get_val, u64 assign_val,
|
||||
struct kunit *test, struct drm_exec *exec)
|
||||
@@ -609,6 +834,23 @@ static struct kunit_case xe_bo_tests[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DRM_XE_DEBUG_PAGE_SIZE
|
||||
static struct kunit_case xe_bo_page_size_alloc_cases[] = {
|
||||
KUNIT_CASE_PARAM(xe_bo_page_size_alloc_only_2m, xe_pci_live_device_gen_param),
|
||||
KUNIT_CASE_PARAM(xe_bo_page_size_alloc_only_1g, xe_pci_live_device_gen_param),
|
||||
KUNIT_CASE_PARAM(xe_bo_page_size_alloc_mixed_bos, xe_pci_live_device_gen_param),
|
||||
{}
|
||||
};
|
||||
|
||||
VISIBLE_IF_KUNIT
|
||||
struct kunit_suite xe_bo_page_size_alloc_suite = {
|
||||
.name = "xe_bo_page_size_alloc",
|
||||
.test_cases = xe_bo_page_size_alloc_cases,
|
||||
.init = xe_kunit_helper_xe_device_live_test_init,
|
||||
};
|
||||
EXPORT_SYMBOL_IF_KUNIT(xe_bo_page_size_alloc_suite);
|
||||
#endif
|
||||
|
||||
VISIBLE_IF_KUNIT
|
||||
struct kunit_suite xe_bo_test_suite = {
|
||||
.name = "xe_bo",
|
||||
|
||||
@@ -11,6 +11,9 @@ extern struct kunit_suite xe_dma_buf_test_suite;
|
||||
extern struct kunit_suite xe_migrate_test_suite;
|
||||
extern struct kunit_suite xe_mocs_test_suite;
|
||||
extern struct kunit_suite xe_guc_g2g_test_suite;
|
||||
#ifdef CONFIG_DRM_XE_DEBUG_PAGE_SIZE
|
||||
extern struct kunit_suite xe_bo_page_size_alloc_suite;
|
||||
#endif
|
||||
|
||||
kunit_test_suite(xe_bo_test_suite);
|
||||
kunit_test_suite(xe_bo_shrink_test_suite);
|
||||
@@ -18,6 +21,9 @@ kunit_test_suite(xe_dma_buf_test_suite);
|
||||
kunit_test_suite(xe_migrate_test_suite);
|
||||
kunit_test_suite(xe_mocs_test_suite);
|
||||
kunit_test_suite(xe_guc_g2g_test_suite);
|
||||
#ifdef CONFIG_DRM_XE_DEBUG_PAGE_SIZE
|
||||
kunit_test_suite(xe_bo_page_size_alloc_suite);
|
||||
#endif
|
||||
|
||||
MODULE_AUTHOR("Intel Corporation");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
Reference in New Issue
Block a user