* [PATCH RESEND v9 0/8] Improve test coverage of TTM
@ 2024-01-11 10:28 Karolina Stolarek
2024-01-11 10:28 ` [PATCH RESEND v9 1/8] drm/ttm/tests: Fix argument in ttm_tt_kunit_init() Karolina Stolarek
` (7 more replies)
0 siblings, 8 replies; 12+ messages in thread
From: Karolina Stolarek @ 2024-01-11 10:28 UTC (permalink / raw)
To: dri-devel
Cc: Amaranath Somalapuram, Karolina Stolarek, Christian König,
Andi Shyti
Introduce tests for ttm_bo_validate()/ttm_bo_init_validate() that exercise
simple BO placement as well as eviction (including the case where the evict
domain also requires eviction to fit the incoming buffer). Prepare KUnit
helpers to handle such scenarios and add a mock VRAM manager. This series also
includes some updates to the helpers and more definitions used to define
"special" memory domains (e.g., one that can't allocate resources or is busy),
as well as a drive-by fix for one of the tests.
There are a couple of areas in which this test suite can be improved.
Suggestions for future work can be found in the TODO file, added as the final
patch in the series.
Use kunit_tool script to manually run all the tests:
$ ./tools/testing/kunit/kunit.py run --kunitconfig=drivers/gpu/drm/ttm/tests
To build a kernel with TTM KUnit tests, first enable CONFIG_KUNIT, and
then CONFIG_DRM_TTM_KUNIT_TEST.
Many thanks,
Karolina
v9:
- Drop tests with basic test cases, they are merged now
- Add three final patches -- tests for ttm_tt_(un)populate, eviction testing
and a TODO file, with suggestions on how to improve these tests
- Delete the initialization of spinlock in
ttm_bo_validate_move_fence_signaled(), it not used at all (Andi)
- Just return the error code threaded_fence_signal(), don't save it to a
local variable (Andi)
- Use ttm_bo_unreserve() in tests checking different move fence states (Andi)
v8:
- Add Tested-by tags to commits that introduce tests
- Improve the comment for ttm_bo_reserve_deadlock() subtest (Andi)
- Actually clean up the resource when "error_free_blocks" is hit in
ttm_mock_manager_alloc(). Without that change, we hit
DEBUG_LOCKS_WARN_ON(lock->magic != lock) warning when cleaning up
the resource manager because we try clean up an incomplete, orphaned
resource. That's not good, and this could bite us back in the future.
v7:
- Drop size argument from ttm_place_kunit_init(), it's no longer needed
- Delete a TODO comment from ttm_bo_validate_tests.c
- First evict BOs before calling ttm_resource_manager_set_used() in
ttm_mock_manager_fini()
- Stop calling ttm_resource_manager_cleanup() as a part of the mock manager
fini sequence. It frees a move fence that is allocated via KUnit allocator,
which gets freed again as a part of the test cleanup
- Set use_tt to true in mock manager and stop passing in the flag for it
- Make ttm_dev_empty_funcs static
(drivers/gpu/drm/ttm/tests/ttm_tt_test.c:232:25: sparse: sparse:
symbol 'ttm_dev_empty_funcs' was not declared. Should it be static?)
- Cast bo->base.resv->fences to a generic pointer before it's checked by
KUnit (drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c:98:9:
sparse: sparse: incompatible types in comparison expression (different
base types))
- Clean up mock managers in ttm_bo_validate_move_fence_not_signaled subtest
v6:
- Include tests for ttm_bo_init_reserved() and ttm_bo_validate(), with
a mock resource manager (patches 6-8; no eviction testing)
- Add ttm_test_devices_all_init() helper to also init ttm_device instance
- Remove fpfn and lpfn from ttm_place_kunit_init() helper -- these fields
are neither used nor tested
v5:
- Actually use the page_flags parameter in ttm_tt_simple_create()
v4:
- First unreserve the object before calling ww_acquire_fini() in
ttm_bo_reserve_double_resv subtest
- Silence lockdep in ttm_bo_reserve_deadlock subtest (open to suggestions
how to fix it in a different way)
- Use a genuine GEM object in ttm_buffer_object instead of an empty one
v3:
- Instead of modifying the main TTM Makefile, use
EXPORT_SYMBOL_FOR_TESTS_ONLY() macro for symbols that are tested but
not widely exported. Thanks to this change, TTM tests can be built
as modules, even when non-exported functions are used
- Change the description of a patch that fixes ttm_pool_pre_populated()
v2:
- Remove Makefile for KUnit tests and move the definitions to the
TTM's one
- Switch on CONFIG_DRM_TTM_KUNIT_TEST=m so the tests and TTM module
are built as one. This allows building the tests as a module, even
if it uses functions that are not exported
- Fix ttm_pool_pre_populated(); a wrong flag was passed to
ttm_tt_kunit_init() function
Karolina Stolarek (8):
drm/ttm/tests: Fix argument in ttm_tt_kunit_init()
drm/ttm/tests: Use an init function from the helpers lib
drm/ttm/tests: Test simple BO creation and validation
drm/ttm/tests: Add tests with mock resource managers
drm/ttm/tests: Add test cases dependent on fence signaling
drm/ttm/tests: Add eviction testing
drm/ttm/tests: Add tests for ttm_tt_populate
drm/ttm/tests: Add TODO file
drivers/gpu/drm/Kconfig | 1 +
drivers/gpu/drm/ttm/tests/.kunitconfig | 1 +
drivers/gpu/drm/ttm/tests/Makefile | 2 +
drivers/gpu/drm/ttm/tests/TODO | 24 +
.../gpu/drm/ttm/tests/ttm_bo_validate_test.c | 1218 +++++++++++++++++
drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c | 176 ++-
drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.h | 11 +
drivers/gpu/drm/ttm/tests/ttm_mock_manager.c | 235 ++++
drivers/gpu/drm/ttm/tests/ttm_mock_manager.h | 33 +
drivers/gpu/drm/ttm/tests/ttm_pool_test.c | 3 +-
drivers/gpu/drm/ttm/tests/ttm_tt_test.c | 134 +-
drivers/gpu/drm/ttm/ttm_tt.c | 3 +
12 files changed, 1816 insertions(+), 25 deletions(-)
create mode 100644 drivers/gpu/drm/ttm/tests/TODO
create mode 100644 drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c
create mode 100644 drivers/gpu/drm/ttm/tests/ttm_mock_manager.c
create mode 100644 drivers/gpu/drm/ttm/tests/ttm_mock_manager.h
--
2.34.1
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH RESEND v9 1/8] drm/ttm/tests: Fix argument in ttm_tt_kunit_init()
2024-01-11 10:28 [PATCH RESEND v9 0/8] Improve test coverage of TTM Karolina Stolarek
@ 2024-01-11 10:28 ` Karolina Stolarek
2024-01-11 14:59 ` Christian König
2024-01-11 10:28 ` [PATCH RESEND v9 2/8] drm/ttm/tests: Use an init function from the helpers lib Karolina Stolarek
` (6 subsequent siblings)
7 siblings, 1 reply; 12+ messages in thread
From: Karolina Stolarek @ 2024-01-11 10:28 UTC (permalink / raw)
To: dri-devel
Cc: Amaranath Somalapuram, Karolina Stolarek, Christian König,
Andi Shyti, Dominik Karol Piątkowski
Remove a leftover definition of page order and pass an empty flag value
in ttm_pool_pre_populated().
Signed-off-by: Karolina Stolarek <karolina.stolarek@intel.com>
Tested-by: Amaranath Somalapuram <Amaranath.Somalapuram@amd.com>
Reviewed-by: Dominik Karol Piątkowski <dominik.karol.piatkowski@intel.com>
Acked-by: Christian König <christian.koenig@amd.com>
---
drivers/gpu/drm/ttm/tests/ttm_pool_test.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/ttm/tests/ttm_pool_test.c b/drivers/gpu/drm/ttm/tests/ttm_pool_test.c
index 2d9cae8cd984..b97f7b6daf5b 100644
--- a/drivers/gpu/drm/ttm/tests/ttm_pool_test.c
+++ b/drivers/gpu/drm/ttm/tests/ttm_pool_test.c
@@ -78,10 +78,9 @@ static struct ttm_pool *ttm_pool_pre_populated(struct kunit *test,
struct ttm_test_devices *devs = priv->devs;
struct ttm_pool *pool;
struct ttm_tt *tt;
- unsigned long order = __fls(size / PAGE_SIZE);
int err;
- tt = ttm_tt_kunit_init(test, order, caching, size);
+ tt = ttm_tt_kunit_init(test, 0, caching, size);
KUNIT_ASSERT_NOT_NULL(test, tt);
pool = kunit_kzalloc(test, sizeof(*pool), GFP_KERNEL);
--
2.34.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH RESEND v9 2/8] drm/ttm/tests: Use an init function from the helpers lib
2024-01-11 10:28 [PATCH RESEND v9 0/8] Improve test coverage of TTM Karolina Stolarek
2024-01-11 10:28 ` [PATCH RESEND v9 1/8] drm/ttm/tests: Fix argument in ttm_tt_kunit_init() Karolina Stolarek
@ 2024-01-11 10:28 ` Karolina Stolarek
2024-01-11 10:28 ` [PATCH RESEND v9 3/8] drm/ttm/tests: Test simple BO creation and validation Karolina Stolarek
` (5 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Karolina Stolarek @ 2024-01-11 10:28 UTC (permalink / raw)
To: dri-devel
Cc: Amaranath Somalapuram, Karolina Stolarek, Christian König,
Andi Shyti
Add a new helper function that also initializes the device. Use it in
ttm_tt test suite and delete the local definition.
Signed-off-by: Karolina Stolarek <karolina.stolarek@intel.com>
---
drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c | 14 ++++++++++++++
drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.h | 1 +
drivers/gpu/drm/ttm/tests/ttm_tt_test.c | 15 +--------------
3 files changed, 16 insertions(+), 14 deletions(-)
diff --git a/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c b/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c
index 7b7c1fa805fc..899a54dbe443 100644
--- a/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c
+++ b/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c
@@ -150,6 +150,20 @@ int ttm_test_devices_init(struct kunit *test)
}
EXPORT_SYMBOL_GPL(ttm_test_devices_init);
+int ttm_test_devices_all_init(struct kunit *test)
+{
+ struct ttm_test_devices *priv;
+
+ priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, priv);
+
+ priv = ttm_test_devices_all(test);
+ test->priv = priv;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ttm_test_devices_all_init);
+
void ttm_test_devices_fini(struct kunit *test)
{
ttm_test_devices_put(test, test->priv);
diff --git a/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.h b/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.h
index 2f51c833a536..53bb5834939f 100644
--- a/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.h
+++ b/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.h
@@ -39,6 +39,7 @@ void ttm_test_devices_put(struct kunit *test, struct ttm_test_devices *devs);
/* Generic init/fini for tests that only need DRM/TTM devices */
int ttm_test_devices_init(struct kunit *test);
+int ttm_test_devices_all_init(struct kunit *test);
void ttm_test_devices_fini(struct kunit *test);
#endif // TTM_KUNIT_HELPERS_H
diff --git a/drivers/gpu/drm/ttm/tests/ttm_tt_test.c b/drivers/gpu/drm/ttm/tests/ttm_tt_test.c
index fd4502c18de6..a33a426a814d 100644
--- a/drivers/gpu/drm/ttm/tests/ttm_tt_test.c
+++ b/drivers/gpu/drm/ttm/tests/ttm_tt_test.c
@@ -15,19 +15,6 @@ struct ttm_tt_test_case {
uint32_t extra_pages_num;
};
-static int ttm_tt_test_init(struct kunit *test)
-{
- struct ttm_test_devices *priv;
-
- priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
- KUNIT_ASSERT_NOT_NULL(test, priv);
-
- priv = ttm_test_devices_all(test);
- test->priv = priv;
-
- return 0;
-}
-
static const struct ttm_tt_test_case ttm_tt_init_basic_cases[] = {
{
.description = "Page-aligned size",
@@ -285,7 +272,7 @@ static struct kunit_case ttm_tt_test_cases[] = {
static struct kunit_suite ttm_tt_test_suite = {
.name = "ttm_tt",
- .init = ttm_tt_test_init,
+ .init = ttm_test_devices_all_init,
.exit = ttm_test_devices_fini,
.test_cases = ttm_tt_test_cases,
};
--
2.34.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH RESEND v9 3/8] drm/ttm/tests: Test simple BO creation and validation
2024-01-11 10:28 [PATCH RESEND v9 0/8] Improve test coverage of TTM Karolina Stolarek
2024-01-11 10:28 ` [PATCH RESEND v9 1/8] drm/ttm/tests: Fix argument in ttm_tt_kunit_init() Karolina Stolarek
2024-01-11 10:28 ` [PATCH RESEND v9 2/8] drm/ttm/tests: Use an init function from the helpers lib Karolina Stolarek
@ 2024-01-11 10:28 ` Karolina Stolarek
2024-01-11 10:28 ` [PATCH RESEND v9 4/8] drm/ttm/tests: Add tests with mock resource managers Karolina Stolarek
` (4 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Karolina Stolarek @ 2024-01-11 10:28 UTC (permalink / raw)
To: dri-devel
Cc: Amaranath Somalapuram, Karolina Stolarek, Christian König,
Andi Shyti
Add tests for ttm_bo_init_reserved() and ttm_bo_validate() that use
sys manager. Define a simple move function in ttm_device_funcs. Expose
destroy callback of the buffer object to make testing of
ttm_bo_init_reserved() behaviour easier.
Signed-off-by: Karolina Stolarek <karolina.stolarek@intel.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Tested-by: Amaranath Somalapuram <Amaranath.Somalapuram@amd.com>
---
drivers/gpu/drm/ttm/tests/Makefile | 1 +
.../gpu/drm/ttm/tests/ttm_bo_validate_test.c | 211 ++++++++++++++++++
drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c | 14 +-
drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.h | 1 +
4 files changed, 226 insertions(+), 1 deletion(-)
create mode 100644 drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c
diff --git a/drivers/gpu/drm/ttm/tests/Makefile b/drivers/gpu/drm/ttm/tests/Makefile
index 468535f7eed2..2e5ed63fb414 100644
--- a/drivers/gpu/drm/ttm/tests/Makefile
+++ b/drivers/gpu/drm/ttm/tests/Makefile
@@ -6,4 +6,5 @@ obj-$(CONFIG_DRM_TTM_KUNIT_TEST) += \
ttm_resource_test.o \
ttm_tt_test.o \
ttm_bo_test.o \
+ ttm_bo_validate_test.o \
ttm_kunit_helpers.o
diff --git a/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c b/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c
new file mode 100644
index 000000000000..1d50e4ba9775
--- /dev/null
+++ b/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c
@@ -0,0 +1,211 @@
+// SPDX-License-Identifier: GPL-2.0 AND MIT
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#include <drm/ttm/ttm_resource.h>
+#include <drm/ttm/ttm_placement.h>
+#include <drm/ttm/ttm_tt.h>
+
+#include "ttm_kunit_helpers.h"
+
+#define BO_SIZE SZ_4K
+
+struct ttm_bo_validate_test_case {
+ const char *description;
+ enum ttm_bo_type bo_type;
+ bool with_ttm;
+};
+
+static struct ttm_placement *ttm_placement_kunit_init(struct kunit *test,
+ struct ttm_place *places,
+ unsigned int num_places,
+ struct ttm_place *busy_places,
+ unsigned int num_busy_places)
+{
+ struct ttm_placement *placement;
+
+ placement = kunit_kzalloc(test, sizeof(*placement), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, placement);
+
+ placement->num_placement = num_places;
+ placement->placement = places;
+ placement->num_busy_placement = num_busy_places;
+ placement->busy_placement = busy_places;
+
+ return placement;
+}
+
+static void ttm_bo_validate_case_desc(const struct ttm_bo_validate_test_case *t,
+ char *desc)
+{
+ strscpy(desc, t->description, KUNIT_PARAM_DESC_SIZE);
+}
+
+static const struct ttm_bo_validate_test_case ttm_bo_type_cases[] = {
+ {
+ .description = "Buffer object for userspace",
+ .bo_type = ttm_bo_type_device,
+ },
+ {
+ .description = "Kernel buffer object",
+ .bo_type = ttm_bo_type_kernel,
+ },
+ {
+ .description = "Shared buffer object",
+ .bo_type = ttm_bo_type_sg,
+ },
+};
+
+KUNIT_ARRAY_PARAM(ttm_bo_types, ttm_bo_type_cases,
+ ttm_bo_validate_case_desc);
+
+static void ttm_bo_init_reserved_sys_man(struct kunit *test)
+{
+ const struct ttm_bo_validate_test_case *params = test->param_value;
+ struct ttm_test_devices *priv = test->priv;
+ struct ttm_buffer_object *bo;
+ struct ttm_place *place;
+ struct ttm_placement *placement;
+ enum ttm_bo_type bo_type = params->bo_type;
+ struct ttm_operation_ctx ctx = { };
+ uint32_t size = ALIGN(BO_SIZE, PAGE_SIZE);
+ int err;
+
+ bo = kunit_kzalloc(test, sizeof(*bo), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, bo);
+
+ place = ttm_place_kunit_init(test, TTM_PL_SYSTEM, 0);
+ placement = ttm_placement_kunit_init(test, place, 1, NULL, 0);
+
+ drm_gem_private_object_init(priv->drm, &bo->base, size);
+
+ err = ttm_bo_init_reserved(priv->ttm_dev, bo, bo_type, placement,
+ PAGE_SIZE, &ctx, NULL, NULL,
+ &dummy_ttm_bo_destroy);
+ dma_resv_unlock(bo->base.resv);
+
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_EXPECT_EQ(test, kref_read(&bo->kref), 1);
+ KUNIT_EXPECT_PTR_EQ(test, bo->bdev, priv->ttm_dev);
+ KUNIT_EXPECT_EQ(test, bo->type, bo_type);
+ KUNIT_EXPECT_EQ(test, bo->page_alignment, PAGE_SIZE);
+ KUNIT_EXPECT_PTR_EQ(test, bo->destroy, &dummy_ttm_bo_destroy);
+ KUNIT_EXPECT_EQ(test, bo->pin_count, 0);
+ KUNIT_EXPECT_NULL(test, bo->bulk_move);
+ KUNIT_EXPECT_NOT_NULL(test, bo->ttm);
+ KUNIT_EXPECT_FALSE(test, ttm_tt_is_populated(bo->ttm));
+ KUNIT_EXPECT_NOT_NULL(test, (void *)bo->base.resv->fences);
+ KUNIT_EXPECT_EQ(test, ctx.bytes_moved, size);
+
+ if (bo_type != ttm_bo_type_kernel)
+ KUNIT_EXPECT_TRUE(test,
+ drm_mm_node_allocated(&bo->base.vma_node.vm_node));
+
+ ttm_resource_free(bo, &bo->resource);
+ ttm_bo_put(bo);
+}
+
+static void ttm_bo_init_reserved_resv(struct kunit *test)
+{
+ struct ttm_test_devices *priv = test->priv;
+ struct ttm_buffer_object *bo;
+ struct ttm_place *place;
+ struct ttm_placement *placement;
+ struct dma_resv resv;
+ enum ttm_bo_type bo_type = ttm_bo_type_device;
+ struct ttm_operation_ctx ctx = { };
+ uint32_t size = ALIGN(BO_SIZE, PAGE_SIZE);
+ int err;
+
+ bo = kunit_kzalloc(test, sizeof(*bo), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, bo);
+
+ place = ttm_place_kunit_init(test, TTM_PL_SYSTEM, 0);
+ placement = ttm_placement_kunit_init(test, place, 1, NULL, 0);
+
+ drm_gem_private_object_init(priv->drm, &bo->base, size);
+ dma_resv_init(&resv);
+ dma_resv_lock(&resv, NULL);
+
+ err = ttm_bo_init_reserved(priv->ttm_dev, bo, bo_type, placement,
+ PAGE_SIZE, &ctx, NULL, &resv,
+ &dummy_ttm_bo_destroy);
+ dma_resv_unlock(bo->base.resv);
+
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_EXPECT_PTR_EQ(test, bo->base.resv, &resv);
+
+ ttm_resource_free(bo, &bo->resource);
+ ttm_bo_put(bo);
+}
+
+static void ttm_bo_validate_invalid_placement(struct kunit *test)
+{
+ struct ttm_buffer_object *bo;
+ struct ttm_place *place;
+ struct ttm_placement *placement;
+ enum ttm_bo_type bo_type = ttm_bo_type_device;
+ struct ttm_operation_ctx ctx = { };
+ uint32_t size = ALIGN(BO_SIZE, PAGE_SIZE);
+ uint32_t unknown_mem_type = TTM_PL_PRIV + 1;
+ int err;
+
+ place = ttm_place_kunit_init(test, unknown_mem_type, 0);
+ placement = ttm_placement_kunit_init(test, place, 1, NULL, 0);
+
+ bo = ttm_bo_kunit_init(test, test->priv, size);
+ bo->type = bo_type;
+
+ ttm_bo_reserve(bo, false, false, NULL);
+ err = ttm_bo_validate(bo, placement, &ctx);
+ dma_resv_unlock(bo->base.resv);
+
+ KUNIT_EXPECT_EQ(test, err, -EINVAL);
+
+ ttm_bo_put(bo);
+}
+
+static void ttm_bo_validate_pinned(struct kunit *test)
+{
+ struct ttm_buffer_object *bo;
+ struct ttm_place *place;
+ struct ttm_placement *placement;
+ uint32_t mem_type = TTM_PL_SYSTEM;
+ enum ttm_bo_type bo_type = ttm_bo_type_device;
+ struct ttm_operation_ctx ctx = { };
+ uint32_t size = ALIGN(BO_SIZE, PAGE_SIZE);
+ int err;
+
+ place = ttm_place_kunit_init(test, mem_type, 0);
+ placement = ttm_placement_kunit_init(test, place, 1, NULL, 0);
+
+ bo = ttm_bo_kunit_init(test, test->priv, size);
+ bo->type = bo_type;
+
+ ttm_bo_reserve(bo, false, false, NULL);
+ ttm_bo_pin(bo);
+ err = ttm_bo_validate(bo, placement, &ctx);
+ dma_resv_unlock(bo->base.resv);
+
+ KUNIT_EXPECT_EQ(test, err, -EINVAL);
+}
+
+static struct kunit_case ttm_bo_validate_test_cases[] = {
+ KUNIT_CASE_PARAM(ttm_bo_init_reserved_sys_man, ttm_bo_types_gen_params),
+ KUNIT_CASE(ttm_bo_init_reserved_resv),
+ KUNIT_CASE(ttm_bo_validate_invalid_placement),
+ KUNIT_CASE(ttm_bo_validate_pinned),
+ {}
+};
+
+static struct kunit_suite ttm_bo_validate_test_suite = {
+ .name = "ttm_bo_validate",
+ .init = ttm_test_devices_all_init,
+ .exit = ttm_test_devices_fini,
+ .test_cases = ttm_bo_validate_test_cases,
+};
+
+kunit_test_suites(&ttm_bo_validate_test_suite);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c b/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c
index 899a54dbe443..b07ea760d819 100644
--- a/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c
+++ b/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c
@@ -22,13 +22,19 @@ static void ttm_tt_simple_destroy(struct ttm_device *bdev, struct ttm_tt *ttm)
kfree(ttm);
}
-static void dummy_ttm_bo_destroy(struct ttm_buffer_object *bo)
+static int mock_move(struct ttm_buffer_object *bo, bool evict,
+ struct ttm_operation_ctx *ctx,
+ struct ttm_resource *new_mem,
+ struct ttm_place *hop)
{
+ bo->resource = new_mem;
+ return 0;
}
struct ttm_device_funcs ttm_dev_funcs = {
.ttm_tt_create = ttm_tt_simple_create,
.ttm_tt_destroy = ttm_tt_simple_destroy,
+ .move = mock_move,
};
EXPORT_SYMBOL_GPL(ttm_dev_funcs);
@@ -88,6 +94,12 @@ struct ttm_place *ttm_place_kunit_init(struct kunit *test,
}
EXPORT_SYMBOL_GPL(ttm_place_kunit_init);
+void dummy_ttm_bo_destroy(struct ttm_buffer_object *bo)
+{
+ drm_gem_object_release(&bo->base);
+}
+EXPORT_SYMBOL_GPL(dummy_ttm_bo_destroy);
+
struct ttm_test_devices *ttm_test_devices_basic(struct kunit *test)
{
struct ttm_test_devices *devs;
diff --git a/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.h b/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.h
index 53bb5834939f..3e5fe272c54c 100644
--- a/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.h
+++ b/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.h
@@ -31,6 +31,7 @@ struct ttm_buffer_object *ttm_bo_kunit_init(struct kunit *test,
size_t size);
struct ttm_place *ttm_place_kunit_init(struct kunit *test,
uint32_t mem_type, uint32_t flags);
+void dummy_ttm_bo_destroy(struct ttm_buffer_object *bo);
struct ttm_test_devices *ttm_test_devices_basic(struct kunit *test);
struct ttm_test_devices *ttm_test_devices_all(struct kunit *test);
--
2.34.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH RESEND v9 4/8] drm/ttm/tests: Add tests with mock resource managers
2024-01-11 10:28 [PATCH RESEND v9 0/8] Improve test coverage of TTM Karolina Stolarek
` (2 preceding siblings ...)
2024-01-11 10:28 ` [PATCH RESEND v9 3/8] drm/ttm/tests: Test simple BO creation and validation Karolina Stolarek
@ 2024-01-11 10:28 ` Karolina Stolarek
2024-01-11 10:28 ` [PATCH RESEND v9 5/8] drm/ttm/tests: Add test cases dependent on fence signaling Karolina Stolarek
` (3 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Karolina Stolarek @ 2024-01-11 10:28 UTC (permalink / raw)
To: dri-devel
Cc: Amaranath Somalapuram, Karolina Stolarek, Christian König,
Andi Shyti
Add mock resource manager to test ttm_bo_validate() with non-system
placements. Update KConfig entry to enable DRM Buddy allocator, used
by the mock manager. Update move function to do more than just assign
a resource.
Signed-off-by: Karolina Stolarek <karolina.stolarek@intel.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Tested-by: Amaranath Somalapuram <Amaranath.Somalapuram@amd.com>
---
drivers/gpu/drm/Kconfig | 1 +
drivers/gpu/drm/ttm/tests/.kunitconfig | 1 +
drivers/gpu/drm/ttm/tests/Makefile | 1 +
.../gpu/drm/ttm/tests/ttm_bo_validate_test.c | 276 ++++++++++++++++++
drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c | 39 ++-
drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.h | 2 +
drivers/gpu/drm/ttm/tests/ttm_mock_manager.c | 207 +++++++++++++
drivers/gpu/drm/ttm/tests/ttm_mock_manager.h | 31 ++
8 files changed, 556 insertions(+), 2 deletions(-)
create mode 100644 drivers/gpu/drm/ttm/tests/ttm_mock_manager.c
create mode 100644 drivers/gpu/drm/ttm/tests/ttm_mock_manager.h
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 6ec33d36f3a4..b9b464fc4dd7 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -201,6 +201,7 @@ config DRM_TTM_KUNIT_TEST
default n
depends on DRM && KUNIT && MMU
select DRM_TTM
+ select DRM_BUDDY
select DRM_EXPORT_FOR_TESTS if m
select DRM_KUNIT_TEST_HELPERS
default KUNIT_ALL_TESTS
diff --git a/drivers/gpu/drm/ttm/tests/.kunitconfig b/drivers/gpu/drm/ttm/tests/.kunitconfig
index 75fdce0cd98e..9228ce9b913c 100644
--- a/drivers/gpu/drm/ttm/tests/.kunitconfig
+++ b/drivers/gpu/drm/ttm/tests/.kunitconfig
@@ -2,3 +2,4 @@ CONFIG_KUNIT=y
CONFIG_DRM=y
CONFIG_DRM_KUNIT_TEST_HELPERS=y
CONFIG_DRM_TTM_KUNIT_TEST=y
+CONFIG_DRM_BUDDY=y
diff --git a/drivers/gpu/drm/ttm/tests/Makefile b/drivers/gpu/drm/ttm/tests/Makefile
index 2e5ed63fb414..f3149de77541 100644
--- a/drivers/gpu/drm/ttm/tests/Makefile
+++ b/drivers/gpu/drm/ttm/tests/Makefile
@@ -7,4 +7,5 @@ obj-$(CONFIG_DRM_TTM_KUNIT_TEST) += \
ttm_tt_test.o \
ttm_bo_test.o \
ttm_bo_validate_test.o \
+ ttm_mock_manager.o \
ttm_kunit_helpers.o
diff --git a/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c b/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c
index 1d50e4ba9775..5f6c24979f83 100644
--- a/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c
+++ b/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c
@@ -8,12 +8,15 @@
#include <drm/ttm/ttm_tt.h>
#include "ttm_kunit_helpers.h"
+#include "ttm_mock_manager.h"
#define BO_SIZE SZ_4K
+#define MANAGER_SIZE SZ_1M
struct ttm_bo_validate_test_case {
const char *description;
enum ttm_bo_type bo_type;
+ uint32_t mem_type;
bool with_ttm;
};
@@ -106,6 +109,49 @@ static void ttm_bo_init_reserved_sys_man(struct kunit *test)
ttm_bo_put(bo);
}
+static void ttm_bo_init_reserved_mock_man(struct kunit *test)
+{
+ const struct ttm_bo_validate_test_case *params = test->param_value;
+ struct ttm_test_devices *priv = test->priv;
+ struct ttm_buffer_object *bo;
+ struct ttm_place *place;
+ struct ttm_placement *placement;
+ enum ttm_bo_type bo_type = params->bo_type;
+ struct ttm_operation_ctx ctx = { };
+ uint32_t mem_type = TTM_PL_VRAM;
+ uint32_t size = ALIGN(BO_SIZE, PAGE_SIZE);
+ int err;
+
+ ttm_mock_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE);
+
+ bo = kunit_kzalloc(test, sizeof(*bo), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, bo);
+
+ place = ttm_place_kunit_init(test, mem_type, 0);
+ placement = ttm_placement_kunit_init(test, place, 1, NULL, 0);
+
+ drm_gem_private_object_init(priv->drm, &bo->base, size);
+
+ err = ttm_bo_init_reserved(priv->ttm_dev, bo, bo_type, placement,
+ PAGE_SIZE, &ctx, NULL, NULL,
+ &dummy_ttm_bo_destroy);
+ dma_resv_unlock(bo->base.resv);
+
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_EXPECT_EQ(test, kref_read(&bo->kref), 1);
+ KUNIT_EXPECT_PTR_EQ(test, bo->bdev, priv->ttm_dev);
+ KUNIT_EXPECT_EQ(test, bo->type, bo_type);
+ KUNIT_EXPECT_EQ(test, ctx.bytes_moved, size);
+
+ if (bo_type != ttm_bo_type_kernel)
+ KUNIT_EXPECT_TRUE(test,
+ drm_mm_node_allocated(&bo->base.vma_node.vm_node));
+
+ ttm_resource_free(bo, &bo->resource);
+ ttm_bo_put(bo);
+ ttm_mock_manager_fini(priv->ttm_dev, mem_type);
+}
+
static void ttm_bo_init_reserved_resv(struct kunit *test)
{
struct ttm_test_devices *priv = test->priv;
@@ -140,6 +186,51 @@ static void ttm_bo_init_reserved_resv(struct kunit *test)
ttm_bo_put(bo);
}
+static void ttm_bo_validate_basic(struct kunit *test)
+{
+ const struct ttm_bo_validate_test_case *params = test->param_value;
+ struct ttm_test_devices *priv = test->priv;
+ struct ttm_buffer_object *bo;
+ struct ttm_place *fst_place, *snd_place;
+ struct ttm_placement *fst_placement, *snd_placement;
+ struct ttm_operation_ctx ctx_init = { }, ctx_val = { };
+ uint32_t size = ALIGN(SZ_8K, PAGE_SIZE);
+ uint32_t fst_mem = TTM_PL_SYSTEM, snd_mem = TTM_PL_VRAM;
+ int err;
+
+ ttm_mock_manager_init(priv->ttm_dev, snd_mem, MANAGER_SIZE);
+
+ fst_place = ttm_place_kunit_init(test, fst_mem, 0);
+ fst_placement = ttm_placement_kunit_init(test, fst_place, 1, NULL, 0);
+
+ bo = kunit_kzalloc(test, sizeof(*bo), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, bo);
+
+ drm_gem_private_object_init(priv->drm, &bo->base, size);
+
+ err = ttm_bo_init_reserved(priv->ttm_dev, bo, params->bo_type,
+ fst_placement, PAGE_SIZE, &ctx_init, NULL,
+ NULL, &dummy_ttm_bo_destroy);
+ KUNIT_EXPECT_EQ(test, err, 0);
+
+ snd_place = ttm_place_kunit_init(test, snd_mem, DRM_BUDDY_TOPDOWN_ALLOCATION);
+ snd_placement = ttm_placement_kunit_init(test, snd_place, 1, NULL, 0);
+
+ err = ttm_bo_validate(bo, snd_placement, &ctx_val);
+ dma_resv_unlock(bo->base.resv);
+
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_EXPECT_EQ(test, ctx_val.bytes_moved, bo->base.size);
+ KUNIT_EXPECT_NOT_NULL(test, bo->ttm);
+ KUNIT_EXPECT_TRUE(test, ttm_tt_is_populated(bo->ttm));
+ KUNIT_EXPECT_EQ(test, bo->resource->mem_type, snd_mem);
+ KUNIT_EXPECT_EQ(test, bo->resource->placement,
+ DRM_BUDDY_TOPDOWN_ALLOCATION);
+
+ ttm_bo_put(bo);
+ ttm_mock_manager_fini(priv->ttm_dev, snd_mem);
+}
+
static void ttm_bo_validate_invalid_placement(struct kunit *test)
{
struct ttm_buffer_object *bo;
@@ -166,6 +257,36 @@ static void ttm_bo_validate_invalid_placement(struct kunit *test)
ttm_bo_put(bo);
}
+static void ttm_bo_validate_failed_alloc(struct kunit *test)
+{
+ struct ttm_test_devices *priv = test->priv;
+ struct ttm_buffer_object *bo;
+ struct ttm_place *place;
+ struct ttm_placement *placement;
+ uint32_t mem_type = TTM_PL_VRAM;
+ enum ttm_bo_type bo_type = ttm_bo_type_device;
+ struct ttm_operation_ctx ctx = { };
+ uint32_t size = ALIGN(BO_SIZE, PAGE_SIZE);
+ int err;
+
+ bo = ttm_bo_kunit_init(test, test->priv, size);
+ bo->type = bo_type;
+
+ ttm_bad_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE);
+
+ place = ttm_place_kunit_init(test, mem_type, 0);
+ placement = ttm_placement_kunit_init(test, place, 1, NULL, 0);
+
+ ttm_bo_reserve(bo, false, false, NULL);
+ err = ttm_bo_validate(bo, placement, &ctx);
+ dma_resv_unlock(bo->base.resv);
+
+ KUNIT_EXPECT_EQ(test, err, -ENOMEM);
+
+ ttm_bo_put(bo);
+ ttm_bad_manager_fini(priv->ttm_dev, mem_type);
+}
+
static void ttm_bo_validate_pinned(struct kunit *test)
{
struct ttm_buffer_object *bo;
@@ -191,11 +312,166 @@ static void ttm_bo_validate_pinned(struct kunit *test)
KUNIT_EXPECT_EQ(test, err, -EINVAL);
}
+static const struct ttm_bo_validate_test_case ttm_mem_type_cases[] = {
+ {
+ .description = "System manager",
+ .mem_type = TTM_PL_SYSTEM,
+ },
+ {
+ .description = "VRAM manager",
+ .mem_type = TTM_PL_SYSTEM,
+ },
+};
+
+KUNIT_ARRAY_PARAM(ttm_bo_validate_mem, ttm_mem_type_cases,
+ ttm_bo_validate_case_desc);
+
+static void ttm_bo_validate_same_placement(struct kunit *test)
+{
+ const struct ttm_bo_validate_test_case *params = test->param_value;
+ struct ttm_test_devices *priv = test->priv;
+ struct ttm_buffer_object *bo;
+ struct ttm_place *place;
+ struct ttm_placement *placement;
+ struct ttm_operation_ctx ctx_init = { }, ctx_val = { };
+ uint32_t size = ALIGN(BO_SIZE, PAGE_SIZE);
+ int err;
+
+ place = ttm_place_kunit_init(test, params->mem_type, 0);
+ placement = ttm_placement_kunit_init(test, place, 1, NULL, 0);
+
+ if (params->mem_type != TTM_PL_SYSTEM)
+ ttm_mock_manager_init(priv->ttm_dev, params->mem_type, MANAGER_SIZE);
+
+ bo = kunit_kzalloc(test, sizeof(*bo), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, bo);
+
+ drm_gem_private_object_init(priv->drm, &bo->base, size);
+
+ err = ttm_bo_init_reserved(priv->ttm_dev, bo, params->bo_type,
+ placement, PAGE_SIZE, &ctx_init, NULL,
+ NULL, &dummy_ttm_bo_destroy);
+ KUNIT_EXPECT_EQ(test, err, 0);
+
+ err = ttm_bo_validate(bo, placement, &ctx_val);
+ dma_resv_unlock(bo->base.resv);
+
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_EXPECT_EQ(test, ctx_val.bytes_moved, 0);
+
+ if (params->mem_type != TTM_PL_SYSTEM)
+ ttm_mock_manager_fini(priv->ttm_dev, params->mem_type);
+
+ ttm_bo_put(bo);
+}
+
+static void ttm_bo_validate_busy_placement(struct kunit *test)
+{
+ struct ttm_test_devices *priv = test->priv;
+ struct ttm_buffer_object *bo;
+ struct ttm_place *init_place, *place_bad, *place_busy;
+ struct ttm_placement *placement_init, *placement_val;
+ struct ttm_resource_manager *man;
+ enum ttm_bo_type bo_type = ttm_bo_type_device;
+ struct ttm_operation_ctx ctx_init = { }, ctx_val = { };
+ uint32_t fst_mem = TTM_PL_VRAM, snd_mem = TTM_PL_VRAM + 1;
+ uint32_t size = ALIGN(BO_SIZE, PAGE_SIZE);
+ int err;
+
+ ttm_bad_manager_init(priv->ttm_dev, fst_mem, MANAGER_SIZE);
+ ttm_mock_manager_init(priv->ttm_dev, snd_mem, MANAGER_SIZE);
+
+ init_place = ttm_place_kunit_init(test, TTM_PL_SYSTEM, 0);
+ placement_init = ttm_placement_kunit_init(test, init_place, 1, NULL, 0);
+
+ bo = kunit_kzalloc(test, sizeof(*bo), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, bo);
+
+ drm_gem_private_object_init(priv->drm, &bo->base, size);
+
+ err = ttm_bo_init_reserved(priv->ttm_dev, bo, bo_type, placement_init,
+ PAGE_SIZE, &ctx_init, NULL, NULL,
+ &dummy_ttm_bo_destroy);
+ KUNIT_EXPECT_EQ(test, err, 0);
+
+ place_bad = ttm_place_kunit_init(test, fst_mem, 0);
+ place_busy = ttm_place_kunit_init(test, snd_mem, 0);
+ placement_val = ttm_placement_kunit_init(test, place_bad, 1, place_busy, 1);
+
+ err = ttm_bo_validate(bo, placement_val, &ctx_val);
+ dma_resv_unlock(bo->base.resv);
+
+ man = ttm_manager_type(priv->ttm_dev, place_busy->mem_type);
+
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_EXPECT_EQ(test, ctx_val.bytes_moved, bo->base.size);
+ KUNIT_EXPECT_EQ(test, bo->resource->mem_type, snd_mem);
+ KUNIT_ASSERT_TRUE(test, list_is_singular(&man->lru[bo->priority]));
+
+ ttm_bo_put(bo);
+ ttm_bad_manager_fini(priv->ttm_dev, fst_mem);
+ ttm_mock_manager_fini(priv->ttm_dev, snd_mem);
+}
+
+static void ttm_bo_validate_multihop(struct kunit *test)
+{
+ const struct ttm_bo_validate_test_case *params = test->param_value;
+ struct ttm_test_devices *priv = test->priv;
+ struct ttm_buffer_object *bo;
+ struct ttm_place *fst_place, *final_place;
+ struct ttm_placement *placement_init, *placement_val;
+ struct ttm_operation_ctx ctx_init = { }, ctx_val = { };
+ uint32_t size = ALIGN(BO_SIZE, PAGE_SIZE);
+ uint32_t fst_mem = TTM_PL_VRAM, tmp_mem = TTM_PL_TT,
+ final_mem = TTM_PL_MULTIHOP;
+ int err;
+
+ ttm_mock_manager_init(priv->ttm_dev, fst_mem, MANAGER_SIZE);
+ ttm_mock_manager_init(priv->ttm_dev, tmp_mem, MANAGER_SIZE);
+ ttm_mock_manager_init(priv->ttm_dev, final_mem, MANAGER_SIZE);
+
+ fst_place = ttm_place_kunit_init(test, fst_mem, 0);
+ placement_init = ttm_placement_kunit_init(test, fst_place, 1, NULL, 0);
+
+ bo = kunit_kzalloc(test, sizeof(*bo), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, bo);
+
+ drm_gem_private_object_init(priv->drm, &bo->base, size);
+
+ err = ttm_bo_init_reserved(priv->ttm_dev, bo, params->bo_type,
+ placement_init, PAGE_SIZE, &ctx_init, NULL,
+ NULL, &dummy_ttm_bo_destroy);
+ KUNIT_EXPECT_EQ(test, err, 0);
+
+ final_place = ttm_place_kunit_init(test, final_mem, 0);
+ placement_val = ttm_placement_kunit_init(test, final_place, 1, NULL, 0);
+
+ err = ttm_bo_validate(bo, placement_val, &ctx_val);
+ dma_resv_unlock(bo->base.resv);
+
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_EXPECT_EQ(test, ctx_val.bytes_moved, size * 2);
+ KUNIT_EXPECT_EQ(test, bo->resource->mem_type, final_mem);
+
+ ttm_bo_put(bo);
+
+ ttm_mock_manager_fini(priv->ttm_dev, fst_mem);
+ ttm_mock_manager_fini(priv->ttm_dev, tmp_mem);
+ ttm_mock_manager_fini(priv->ttm_dev, final_mem);
+}
+
static struct kunit_case ttm_bo_validate_test_cases[] = {
KUNIT_CASE_PARAM(ttm_bo_init_reserved_sys_man, ttm_bo_types_gen_params),
+ KUNIT_CASE_PARAM(ttm_bo_init_reserved_mock_man, ttm_bo_types_gen_params),
KUNIT_CASE(ttm_bo_init_reserved_resv),
+ KUNIT_CASE_PARAM(ttm_bo_validate_basic, ttm_bo_types_gen_params),
KUNIT_CASE(ttm_bo_validate_invalid_placement),
+ KUNIT_CASE_PARAM(ttm_bo_validate_same_placement,
+ ttm_bo_validate_mem_gen_params),
+ KUNIT_CASE(ttm_bo_validate_failed_alloc),
KUNIT_CASE(ttm_bo_validate_pinned),
+ KUNIT_CASE(ttm_bo_validate_busy_placement),
+ KUNIT_CASE_PARAM(ttm_bo_validate_multihop, ttm_bo_types_gen_params),
{}
};
diff --git a/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c b/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c
index b07ea760d819..719c1d56388e 100644
--- a/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c
+++ b/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c
@@ -27,8 +27,43 @@ static int mock_move(struct ttm_buffer_object *bo, bool evict,
struct ttm_resource *new_mem,
struct ttm_place *hop)
{
- bo->resource = new_mem;
- return 0;
+ struct ttm_resource *old_mem = bo->resource;
+ int ret;
+
+ if (!old_mem || (old_mem->mem_type == TTM_PL_SYSTEM && !bo->ttm)) {
+ ttm_bo_move_null(bo, new_mem);
+ return 0;
+ }
+
+ /* Dummy multihop */
+ if (bo->resource->mem_type == TTM_PL_VRAM &&
+ new_mem->mem_type == TTM_PL_MULTIHOP) {
+ hop->mem_type = TTM_PL_TT;
+ hop->flags = TTM_PL_FLAG_TEMPORARY;
+ hop->fpfn = 0;
+ hop->lpfn = 0;
+ return -EMULTIHOP;
+ }
+
+ if (old_mem->mem_type == TTM_PL_SYSTEM &&
+ new_mem->mem_type == TTM_PL_TT) {
+ ttm_bo_move_null(bo, new_mem);
+ return 0;
+ }
+
+ if (old_mem->mem_type == TTM_PL_TT &&
+ new_mem->mem_type == TTM_PL_SYSTEM) {
+ ret = ttm_bo_wait_ctx(bo, ctx);
+
+ if (ret)
+ return ret;
+
+ ttm_resource_free(bo, &bo->resource);
+ ttm_bo_assign_mem(bo, new_mem);
+ return 0;
+ }
+
+ return ttm_bo_move_memcpy(bo, ctx, new_mem);
}
struct ttm_device_funcs ttm_dev_funcs = {
diff --git a/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.h b/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.h
index 3e5fe272c54c..a8977eb606e5 100644
--- a/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.h
+++ b/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.h
@@ -13,6 +13,8 @@
#include <drm/drm_kunit_helpers.h>
#include <kunit/test.h>
+#define TTM_PL_MULTIHOP (TTM_PL_PRIV + 1)
+
extern struct ttm_device_funcs ttm_dev_funcs;
struct ttm_test_devices {
diff --git a/drivers/gpu/drm/ttm/tests/ttm_mock_manager.c b/drivers/gpu/drm/ttm/tests/ttm_mock_manager.c
new file mode 100644
index 000000000000..21636b96ac38
--- /dev/null
+++ b/drivers/gpu/drm/ttm/tests/ttm_mock_manager.c
@@ -0,0 +1,207 @@
+// SPDX-License-Identifier: GPL-2.0 AND MIT
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+#include <drm/ttm/ttm_resource.h>
+#include <drm/ttm/ttm_device.h>
+#include <drm/ttm/ttm_placement.h>
+
+#include "ttm_mock_manager.h"
+
+static inline struct ttm_mock_manager *
+to_mock_mgr(struct ttm_resource_manager *man)
+{
+ return container_of(man, struct ttm_mock_manager, man);
+}
+
+static inline struct ttm_mock_resource *
+to_mock_mgr_resource(struct ttm_resource *res)
+{
+ return container_of(res, struct ttm_mock_resource, base);
+}
+
+static int ttm_mock_manager_alloc(struct ttm_resource_manager *man,
+ struct ttm_buffer_object *bo,
+ const struct ttm_place *place,
+ struct ttm_resource **res)
+{
+ struct ttm_mock_manager *manager = to_mock_mgr(man);
+ struct ttm_mock_resource *mock_res;
+ struct drm_buddy *mm = &manager->mm;
+ uint64_t lpfn, fpfn, alloc_size;
+ int err;
+
+ mock_res = kzalloc(sizeof(*mock_res), GFP_KERNEL);
+
+ if (!mock_res)
+ return -ENOMEM;
+
+ fpfn = 0;
+ lpfn = man->size;
+
+ ttm_resource_init(bo, place, &mock_res->base);
+ INIT_LIST_HEAD(&mock_res->blocks);
+
+ if (place->flags & TTM_PL_FLAG_TOPDOWN)
+ mock_res->flags |= DRM_BUDDY_TOPDOWN_ALLOCATION;
+
+ if (place->flags & TTM_PL_FLAG_CONTIGUOUS)
+ mock_res->flags |= DRM_BUDDY_CONTIGUOUS_ALLOCATION;
+
+ alloc_size = (uint64_t)mock_res->base.size;
+ mutex_lock(&manager->lock);
+ err = drm_buddy_alloc_blocks(mm, fpfn, lpfn, alloc_size,
+ manager->default_page_size,
+ &mock_res->blocks,
+ mock_res->flags);
+
+ if (err)
+ goto error_free_blocks;
+ mutex_unlock(&manager->lock);
+
+ *res = &mock_res->base;
+ return 0;
+
+error_free_blocks:
+ drm_buddy_free_list(mm, &mock_res->blocks);
+ ttm_resource_fini(man, &mock_res->base);
+ mutex_unlock(&manager->lock);
+
+ return err;
+}
+
+static void ttm_mock_manager_free(struct ttm_resource_manager *man,
+ struct ttm_resource *res)
+{
+ struct ttm_mock_manager *manager = to_mock_mgr(man);
+ struct ttm_mock_resource *mock_res = to_mock_mgr_resource(res);
+ struct drm_buddy *mm = &manager->mm;
+
+ mutex_lock(&manager->lock);
+ drm_buddy_free_list(mm, &mock_res->blocks);
+ mutex_unlock(&manager->lock);
+
+ ttm_resource_fini(man, res);
+ kfree(mock_res);
+}
+
+static const struct ttm_resource_manager_func ttm_mock_manager_funcs = {
+ .alloc = ttm_mock_manager_alloc,
+ .free = ttm_mock_manager_free,
+};
+
+int ttm_mock_manager_init(struct ttm_device *bdev, uint32_t mem_type, uint32_t size)
+{
+ struct ttm_mock_manager *manager;
+ struct ttm_resource_manager *base;
+ int err;
+
+ manager = kzalloc(sizeof(*manager), GFP_KERNEL);
+ if (!manager)
+ return -ENOMEM;
+
+ mutex_init(&manager->lock);
+
+ err = drm_buddy_init(&manager->mm, size, PAGE_SIZE);
+
+ if (err) {
+ kfree(manager);
+ return err;
+ }
+
+ manager->default_page_size = PAGE_SIZE;
+ base = &manager->man;
+ base->func = &ttm_mock_manager_funcs;
+ base->use_tt = true;
+
+ ttm_resource_manager_init(base, bdev, size);
+ ttm_set_driver_manager(bdev, mem_type, base);
+ ttm_resource_manager_set_used(base, true);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ttm_mock_manager_init);
+
+void ttm_mock_manager_fini(struct ttm_device *bdev, uint32_t mem_type)
+{
+ struct ttm_resource_manager *man;
+ struct ttm_mock_manager *mock_man;
+ int err;
+
+ man = ttm_manager_type(bdev, mem_type);
+ mock_man = to_mock_mgr(man);
+
+ err = ttm_resource_manager_evict_all(bdev, man);
+ if (err)
+ return;
+
+ ttm_resource_manager_set_used(man, false);
+
+ mutex_lock(&mock_man->lock);
+ drm_buddy_fini(&mock_man->mm);
+ mutex_unlock(&mock_man->lock);
+
+ ttm_set_driver_manager(bdev, mem_type, NULL);
+}
+EXPORT_SYMBOL_GPL(ttm_mock_manager_fini);
+
+static int ttm_bad_manager_alloc(struct ttm_resource_manager *man,
+ struct ttm_buffer_object *bo,
+ const struct ttm_place *place,
+ struct ttm_resource **res)
+{
+ return -ENOSPC;
+}
+
+static void ttm_bad_manager_free(struct ttm_resource_manager *man,
+ struct ttm_resource *res)
+{
+}
+
+static bool ttm_bad_manager_compatible(struct ttm_resource_manager *man,
+ struct ttm_resource *res,
+ const struct ttm_place *place,
+ size_t size)
+{
+ return true;
+}
+
+static const struct ttm_resource_manager_func ttm_bad_manager_funcs = {
+ .alloc = ttm_bad_manager_alloc,
+ .free = ttm_bad_manager_free,
+ .compatible = ttm_bad_manager_compatible
+};
+
+int ttm_bad_manager_init(struct ttm_device *bdev, uint32_t mem_type,
+ uint32_t size)
+{
+ struct ttm_resource_manager *man;
+
+ man = kzalloc(sizeof(*man), GFP_KERNEL);
+ if (!man)
+ return -ENOMEM;
+
+ man->func = &ttm_bad_manager_funcs;
+
+ ttm_resource_manager_init(man, bdev, size);
+ ttm_set_driver_manager(bdev, mem_type, man);
+ ttm_resource_manager_set_used(man, true);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ttm_bad_manager_init);
+
+void ttm_bad_manager_fini(struct ttm_device *bdev, uint32_t mem_type)
+{
+ struct ttm_resource_manager *man;
+
+ man = ttm_manager_type(bdev, mem_type);
+
+ ttm_resource_manager_set_used(man, false);
+ ttm_set_driver_manager(bdev, mem_type, NULL);
+
+ kfree(man);
+}
+EXPORT_SYMBOL_GPL(ttm_bad_manager_fini);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/ttm/tests/ttm_mock_manager.h b/drivers/gpu/drm/ttm/tests/ttm_mock_manager.h
new file mode 100644
index 000000000000..d2db9de9d876
--- /dev/null
+++ b/drivers/gpu/drm/ttm/tests/ttm_mock_manager.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0 AND MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+#ifndef TTM_MOCK_MANAGER_H
+#define TTM_MOCK_MANAGER_H
+
+#include <drm/drm_buddy.h>
+
+struct ttm_mock_manager {
+ struct ttm_resource_manager man;
+ struct drm_buddy mm;
+ uint64_t default_page_size;
+ /* protects allocations of mock buffer objects */
+ struct mutex lock;
+};
+
+struct ttm_mock_resource {
+ struct ttm_resource base;
+ struct list_head blocks;
+ unsigned long flags;
+};
+
+int ttm_mock_manager_init(struct ttm_device *bdev, uint32_t mem_type,
+ uint32_t size);
+int ttm_bad_manager_init(struct ttm_device *bdev, uint32_t mem_type,
+ uint32_t size);
+void ttm_mock_manager_fini(struct ttm_device *bdev, uint32_t mem_type);
+void ttm_bad_manager_fini(struct ttm_device *bdev, uint32_t mem_type);
+
+#endif // TTM_MOCK_MANAGER_H
--
2.34.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH RESEND v9 5/8] drm/ttm/tests: Add test cases dependent on fence signaling
2024-01-11 10:28 [PATCH RESEND v9 0/8] Improve test coverage of TTM Karolina Stolarek
` (3 preceding siblings ...)
2024-01-11 10:28 ` [PATCH RESEND v9 4/8] drm/ttm/tests: Add tests with mock resource managers Karolina Stolarek
@ 2024-01-11 10:28 ` Karolina Stolarek
2024-01-11 10:28 ` [PATCH RESEND v9 6/8] drm/ttm/tests: Add eviction testing Karolina Stolarek
` (2 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Karolina Stolarek @ 2024-01-11 10:28 UTC (permalink / raw)
To: dri-devel
Cc: Amaranath Somalapuram, Karolina Stolarek, Christian König,
Andi Shyti
Add test cases that check how the state of dma fences in BO's
reservation object influence the ttm_bo_validation() flow. Do similar
tests for resource manager's move fence.
Signed-off-by: Karolina Stolarek <karolina.stolarek@intel.com>
Tested-by: Amaranath Somalapuram <Amaranath.Somalapuram@amd.com>
---
.../gpu/drm/ttm/tests/ttm_bo_validate_test.c | 305 ++++++++++++++++++
1 file changed, 305 insertions(+)
diff --git a/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c b/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c
index 5f6c24979f83..bf4bae25aec9 100644
--- a/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c
+++ b/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c
@@ -2,6 +2,8 @@
/*
* Copyright © 2023 Intel Corporation
*/
+#include <linux/delay.h>
+#include <linux/kthread.h>
#include <drm/ttm/ttm_resource.h>
#include <drm/ttm/ttm_placement.h>
@@ -13,11 +15,14 @@
#define BO_SIZE SZ_4K
#define MANAGER_SIZE SZ_1M
+static struct spinlock fence_lock;
+
struct ttm_bo_validate_test_case {
const char *description;
enum ttm_bo_type bo_type;
uint32_t mem_type;
bool with_ttm;
+ bool no_gpu_wait;
};
static struct ttm_placement *ttm_placement_kunit_init(struct kunit *test,
@@ -39,6 +44,43 @@ static struct ttm_placement *ttm_placement_kunit_init(struct kunit *test,
return placement;
}
+static const char *fence_name(struct dma_fence *f)
+{
+ return "ttm-bo-validate-fence";
+}
+
+static const struct dma_fence_ops fence_ops = {
+ .get_driver_name = fence_name,
+ .get_timeline_name = fence_name,
+};
+
+static struct dma_fence *alloc_mock_fence(struct kunit *test)
+{
+ struct dma_fence *fence;
+
+ fence = kunit_kzalloc(test, sizeof(*fence), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, fence);
+
+ dma_fence_init(fence, &fence_ops, &fence_lock, 0, 0);
+
+ return fence;
+}
+
+static void dma_resv_kunit_active_fence_init(struct kunit *test,
+ struct dma_resv *resv,
+ enum dma_resv_usage usage)
+{
+ struct dma_fence *fence;
+
+ fence = alloc_mock_fence(test);
+ dma_fence_enable_sw_signaling(fence);
+
+ dma_resv_lock(resv, NULL);
+ dma_resv_reserve_fences(resv, 1);
+ dma_resv_add_fence(resv, fence, usage);
+ dma_resv_unlock(resv);
+}
+
static void ttm_bo_validate_case_desc(const struct ttm_bo_validate_test_case *t,
char *desc)
{
@@ -460,6 +502,262 @@ static void ttm_bo_validate_multihop(struct kunit *test)
ttm_mock_manager_fini(priv->ttm_dev, final_mem);
}
+static const struct ttm_bo_validate_test_case ttm_bo_no_placement_cases[] = {
+ {
+ .description = "Buffer object in system domain, no page vector",
+ },
+ {
+ .description = "Buffer object in system domain with an existing page vector",
+ .with_ttm = true,
+ },
+};
+
+KUNIT_ARRAY_PARAM(ttm_bo_no_placement, ttm_bo_no_placement_cases,
+ ttm_bo_validate_case_desc);
+
+static void ttm_bo_validate_no_placement_signaled(struct kunit *test)
+{
+ const struct ttm_bo_validate_test_case *params = test->param_value;
+ struct ttm_test_devices *priv = test->priv;
+ struct ttm_buffer_object *bo;
+ struct ttm_place *place;
+ struct ttm_tt *old_tt;
+ struct ttm_placement *placement;
+ struct ttm_resource_manager *man;
+ uint32_t mem_type = TTM_PL_SYSTEM;
+ enum ttm_bo_type bo_type = ttm_bo_type_device;
+ struct ttm_operation_ctx ctx = { };
+ uint32_t size = ALIGN(BO_SIZE, PAGE_SIZE);
+ uint32_t flags;
+ int err;
+
+ place = ttm_place_kunit_init(test, mem_type, 0);
+ man = ttm_manager_type(priv->ttm_dev, mem_type);
+
+ bo = ttm_bo_kunit_init(test, test->priv, size);
+ bo->type = bo_type;
+
+ if (params->with_ttm) {
+ old_tt = priv->ttm_dev->funcs->ttm_tt_create(bo, 0);
+ ttm_pool_alloc(&priv->ttm_dev->pool, old_tt, &ctx);
+ bo->ttm = old_tt;
+ }
+
+ err = ttm_resource_alloc(bo, place, &bo->resource);
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_ASSERT_EQ(test, man->usage, size);
+
+ placement = kunit_kzalloc(test, sizeof(*placement), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, placement);
+
+ ttm_bo_reserve(bo, false, false, NULL);
+ err = ttm_bo_validate(bo, placement, &ctx);
+ ttm_bo_unreserve(bo);
+
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_ASSERT_EQ(test, man->usage, 0);
+ KUNIT_ASSERT_NOT_NULL(test, bo->ttm);
+ KUNIT_EXPECT_EQ(test, ctx.bytes_moved, 0);
+
+ if (params->with_ttm) {
+ flags = bo->ttm->page_flags;
+
+ KUNIT_ASSERT_PTR_EQ(test, bo->ttm, old_tt);
+ KUNIT_ASSERT_FALSE(test, flags & TTM_TT_FLAG_PRIV_POPULATED);
+ KUNIT_ASSERT_TRUE(test, flags & TTM_TT_FLAG_ZERO_ALLOC);
+ }
+
+ ttm_bo_put(bo);
+}
+
+static int threaded_dma_resv_signal(void *arg)
+{
+ struct ttm_buffer_object *bo = arg;
+ struct dma_resv *resv = bo->base.resv;
+ struct dma_resv_iter cursor;
+ struct dma_fence *fence;
+
+ dma_resv_iter_begin(&cursor, resv, DMA_RESV_USAGE_BOOKKEEP);
+ dma_resv_for_each_fence_unlocked(&cursor, fence) {
+ dma_fence_signal(fence);
+ }
+ dma_resv_iter_end(&cursor);
+
+ return 0;
+}
+
+static void ttm_bo_validate_no_placement_not_signaled(struct kunit *test)
+{
+ const struct ttm_bo_validate_test_case *params = test->param_value;
+ struct ttm_buffer_object *bo;
+ struct ttm_place *place;
+ struct ttm_placement *placement;
+ struct task_struct *task;
+ enum dma_resv_usage usage = DMA_RESV_USAGE_BOOKKEEP;
+ uint32_t mem_type = TTM_PL_SYSTEM;
+ struct ttm_operation_ctx ctx = { };
+ uint32_t size = ALIGN(BO_SIZE, PAGE_SIZE);
+ int err;
+
+ place = ttm_place_kunit_init(test, mem_type, 0);
+
+ bo = ttm_bo_kunit_init(test, test->priv, size);
+ bo->type = params->bo_type;
+
+ err = ttm_resource_alloc(bo, place, &bo->resource);
+ KUNIT_EXPECT_EQ(test, err, 0);
+
+ placement = kunit_kzalloc(test, sizeof(*placement), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, placement);
+
+ /* Create an active fence to simulate a non-idle resv object */
+ spin_lock_init(&fence_lock);
+ dma_resv_kunit_active_fence_init(test, bo->base.resv, usage);
+
+ task = kthread_create(threaded_dma_resv_signal, bo, "dma-resv-signal");
+ if (IS_ERR(task))
+ KUNIT_FAIL(test, "Couldn't create dma resv signal task\n");
+
+ wake_up_process(task);
+ ttm_bo_reserve(bo, false, false, NULL);
+ err = ttm_bo_validate(bo, placement, &ctx);
+ ttm_bo_unreserve(bo);
+
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_ASSERT_NOT_NULL(test, bo->ttm);
+ KUNIT_ASSERT_NULL(test, bo->resource);
+ KUNIT_ASSERT_NULL(test, bo->bulk_move);
+ KUNIT_EXPECT_EQ(test, ctx.bytes_moved, 0);
+
+ if (bo->type != ttm_bo_type_sg)
+ KUNIT_ASSERT_PTR_EQ(test, bo->base.resv, &bo->base._resv);
+
+ /* Make sure we have an idle object at this point */
+ dma_resv_wait_timeout(bo->base.resv, usage, false, MAX_SCHEDULE_TIMEOUT);
+
+ ttm_bo_put(bo);
+}
+
+static void ttm_bo_validate_move_fence_signaled(struct kunit *test)
+{
+ struct ttm_test_devices *priv = test->priv;
+ struct ttm_buffer_object *bo;
+ struct ttm_place *place;
+ struct ttm_placement *placement;
+ struct ttm_resource_manager *man;
+ enum ttm_bo_type bo_type = ttm_bo_type_device;
+ uint32_t mem_type = TTM_PL_SYSTEM;
+ struct ttm_operation_ctx ctx = { };
+ uint32_t size = ALIGN(BO_SIZE, PAGE_SIZE);
+ int err;
+
+ man = ttm_manager_type(priv->ttm_dev, mem_type);
+ man->move = dma_fence_get_stub();
+
+ bo = ttm_bo_kunit_init(test, test->priv, size);
+ bo->type = bo_type;
+
+ place = ttm_place_kunit_init(test, mem_type, 0);
+ placement = ttm_placement_kunit_init(test, place, 1, NULL, 0);
+
+ ttm_bo_reserve(bo, false, false, NULL);
+ err = ttm_bo_validate(bo, placement, &ctx);
+ ttm_bo_unreserve(bo);
+
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_EXPECT_EQ(test, bo->resource->mem_type, mem_type);
+ KUNIT_EXPECT_EQ(test, ctx.bytes_moved, size);
+
+ ttm_bo_put(bo);
+ dma_fence_put(man->move);
+}
+
+static const struct ttm_bo_validate_test_case ttm_bo_validate_wait_cases[] = {
+ {
+ .description = "Waits for GPU",
+ .no_gpu_wait = false,
+ },
+ {
+ .description = "Tries to lock straight away",
+ .no_gpu_wait = true,
+ },
+};
+
+KUNIT_ARRAY_PARAM(ttm_bo_validate_wait, ttm_bo_validate_wait_cases,
+ ttm_bo_validate_case_desc);
+
+static int threaded_fence_signal(void *arg)
+{
+ struct dma_fence *fence = arg;
+
+ msleep(20);
+
+ return dma_fence_signal(fence);
+}
+
+static void ttm_bo_validate_move_fence_not_signaled(struct kunit *test)
+{
+ const struct ttm_bo_validate_test_case *params = test->param_value;
+ struct ttm_test_devices *priv = test->priv;
+ struct ttm_buffer_object *bo;
+ struct ttm_place *init_place, *fst_place, *snd_place;
+ struct ttm_placement *placement_init, *placement_val;
+ struct task_struct *task;
+ struct ttm_resource_manager *man;
+ enum ttm_bo_type bo_type = ttm_bo_type_device;
+ uint32_t fst_mem = TTM_PL_VRAM, snd_mem = TTM_PL_VRAM + 1;
+ uint32_t size = ALIGN(BO_SIZE, PAGE_SIZE);
+ struct ttm_operation_ctx ctx_init = { },
+ ctx_val = { .no_wait_gpu = params->no_gpu_wait };
+ int err;
+
+ init_place = ttm_place_kunit_init(test, TTM_PL_SYSTEM, 0);
+ placement_init = ttm_placement_kunit_init(test, init_place, 1, NULL, 0);
+
+ bo = kunit_kzalloc(test, sizeof(*bo), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, bo);
+
+ drm_gem_private_object_init(priv->drm, &bo->base, size);
+
+ err = ttm_bo_init_reserved(priv->ttm_dev, bo, bo_type, placement_init,
+ PAGE_SIZE, &ctx_init, NULL, NULL,
+ &dummy_ttm_bo_destroy);
+ KUNIT_EXPECT_EQ(test, err, 0);
+
+ ttm_mock_manager_init(priv->ttm_dev, fst_mem, MANAGER_SIZE);
+ ttm_mock_manager_init(priv->ttm_dev, snd_mem, MANAGER_SIZE);
+
+ fst_place = ttm_place_kunit_init(test, fst_mem, 0);
+ snd_place = ttm_place_kunit_init(test, snd_mem, 0);
+ placement_val = ttm_placement_kunit_init(test, fst_place, 1, snd_place, 1);
+
+ spin_lock_init(&fence_lock);
+ man = ttm_manager_type(priv->ttm_dev, fst_place->mem_type);
+ man->move = alloc_mock_fence(test);
+
+ task = kthread_create(threaded_fence_signal, man->move, "move-fence-signal");
+ if (IS_ERR(task))
+ KUNIT_FAIL(test, "Couldn't create move fence signal task\n");
+
+ wake_up_process(task);
+ err = ttm_bo_validate(bo, placement_val, &ctx_val);
+ dma_resv_unlock(bo->base.resv);
+
+ dma_fence_wait_timeout(man->move, false, MAX_SCHEDULE_TIMEOUT);
+
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_EXPECT_EQ(test, ctx_val.bytes_moved, size);
+
+ if (params->no_gpu_wait)
+ KUNIT_EXPECT_EQ(test, bo->resource->mem_type, snd_mem);
+ else
+ KUNIT_EXPECT_EQ(test, bo->resource->mem_type, fst_mem);
+
+ ttm_bo_put(bo);
+ ttm_mock_manager_fini(priv->ttm_dev, fst_mem);
+ ttm_mock_manager_fini(priv->ttm_dev, snd_mem);
+}
+
static struct kunit_case ttm_bo_validate_test_cases[] = {
KUNIT_CASE_PARAM(ttm_bo_init_reserved_sys_man, ttm_bo_types_gen_params),
KUNIT_CASE_PARAM(ttm_bo_init_reserved_mock_man, ttm_bo_types_gen_params),
@@ -472,6 +770,13 @@ static struct kunit_case ttm_bo_validate_test_cases[] = {
KUNIT_CASE(ttm_bo_validate_pinned),
KUNIT_CASE(ttm_bo_validate_busy_placement),
KUNIT_CASE_PARAM(ttm_bo_validate_multihop, ttm_bo_types_gen_params),
+ KUNIT_CASE_PARAM(ttm_bo_validate_no_placement_signaled,
+ ttm_bo_no_placement_gen_params),
+ KUNIT_CASE_PARAM(ttm_bo_validate_no_placement_not_signaled,
+ ttm_bo_types_gen_params),
+ KUNIT_CASE(ttm_bo_validate_move_fence_signaled),
+ KUNIT_CASE_PARAM(ttm_bo_validate_move_fence_not_signaled,
+ ttm_bo_validate_wait_gen_params),
{}
};
--
2.34.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH RESEND v9 6/8] drm/ttm/tests: Add eviction testing
2024-01-11 10:28 [PATCH RESEND v9 0/8] Improve test coverage of TTM Karolina Stolarek
` (4 preceding siblings ...)
2024-01-11 10:28 ` [PATCH RESEND v9 5/8] drm/ttm/tests: Add test cases dependent on fence signaling Karolina Stolarek
@ 2024-01-11 10:28 ` Karolina Stolarek
2024-01-11 10:28 ` [PATCH RESEND v9 7/8] drm/ttm/tests: Add tests for ttm_tt_populate Karolina Stolarek
2024-01-11 10:28 ` [PATCH RESEND v9 8/8] drm/ttm/tests: Add TODO file Karolina Stolarek
7 siblings, 0 replies; 12+ messages in thread
From: Karolina Stolarek @ 2024-01-11 10:28 UTC (permalink / raw)
To: dri-devel
Cc: Amaranath Somalapuram, Karolina Stolarek, Christian König,
Andi Shyti
Add tests for ttm_bo_validate that focus on BO eviction and swapout.
Update device funcs definition with eviction-related callbacks. Add
alternative funcs where evict_flags() routes eviction to a domain
that can't allocate resources (dubbed "busy manager" in the tests).
Extract the common path of ttm_device init into a function.
Signed-off-by: Karolina Stolarek <karolina.stolarek@intel.com>
---
.../gpu/drm/ttm/tests/ttm_bo_validate_test.c | 426 ++++++++++++++++++
drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c | 113 ++++-
drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.h | 7 +
drivers/gpu/drm/ttm/tests/ttm_mock_manager.c | 28 ++
drivers/gpu/drm/ttm/tests/ttm_mock_manager.h | 2 +
5 files changed, 568 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c b/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c
index bf4bae25aec9..c7aa5e087597 100644
--- a/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c
+++ b/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c
@@ -758,6 +758,424 @@ static void ttm_bo_validate_move_fence_not_signaled(struct kunit *test)
ttm_mock_manager_fini(priv->ttm_dev, snd_mem);
}
+static void ttm_bo_validate_swapout(struct kunit *test)
+{
+ struct ttm_test_devices *priv = test->priv;
+ unsigned long size_big, size = ALIGN(BO_SIZE, PAGE_SIZE);
+ enum ttm_bo_type bo_type = ttm_bo_type_device;
+ struct ttm_operation_ctx ctx = { };
+ uint32_t mem_type = TTM_PL_VRAM;
+ struct ttm_buffer_object *bo_small, *bo_big;
+ struct ttm_place *place;
+ struct ttm_placement *placement;
+ struct sysinfo si;
+ int err;
+
+ si_meminfo(&si);
+ size_big = ALIGN(((uint64_t)si.totalram * si.mem_unit / 2), PAGE_SIZE);
+
+ ttm_mock_manager_init(priv->ttm_dev, mem_type, size_big + size);
+
+ place = ttm_place_kunit_init(test, mem_type, 0);
+ placement = ttm_placement_kunit_init(test, place, 1, NULL, 0);
+
+ bo_small = kunit_kzalloc(test, sizeof(*bo_small), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, bo_small);
+
+ drm_gem_private_object_init(priv->drm, &bo_small->base, size);
+
+ err = ttm_bo_init_reserved(priv->ttm_dev, bo_small, bo_type, placement,
+ PAGE_SIZE, &ctx, NULL, NULL,
+ &dummy_ttm_bo_destroy);
+ KUNIT_EXPECT_EQ(test, err, 0);
+ dma_resv_unlock(bo_small->base.resv);
+
+ bo_big = ttm_bo_kunit_init(test, priv, size_big);
+
+ dma_resv_lock(bo_big->base.resv, NULL);
+ err = ttm_bo_validate(bo_big, placement, &ctx);
+ dma_resv_unlock(bo_big->base.resv);
+
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_EXPECT_NOT_NULL(test, bo_big->resource);
+ KUNIT_EXPECT_EQ(test, bo_big->resource->mem_type, mem_type);
+ KUNIT_EXPECT_EQ(test, bo_small->resource->mem_type, TTM_PL_SYSTEM);
+ KUNIT_EXPECT_TRUE(test, bo_small->ttm->page_flags & TTM_TT_FLAG_SWAPPED);
+
+ ttm_bo_put(bo_big);
+ ttm_bo_put(bo_small);
+
+ ttm_mock_manager_fini(priv->ttm_dev, mem_type);
+}
+
+static void ttm_bo_validate_happy_evict(struct kunit *test)
+{
+ struct ttm_test_devices *priv = test->priv;
+ struct ttm_buffer_object *bos, *bo_val;
+ struct ttm_place *place;
+ struct ttm_placement *placement;
+ enum ttm_bo_type bo_type = ttm_bo_type_device;
+ uint32_t bo_no = 3;
+ uint32_t small = SZ_8K, medium = SZ_512K,
+ big = MANAGER_SIZE - (small + medium);
+ uint32_t bo_sizes[] = { small, medium, big };
+ uint32_t mem_type = TTM_PL_VRAM, mem_type_evict = TTM_PL_SYSTEM;
+ struct ttm_operation_ctx ctx_init = { }, ctx_val = { };
+ int i, err;
+
+ ttm_mock_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE);
+
+ place = ttm_place_kunit_init(test, mem_type, 0);
+ placement = ttm_placement_kunit_init(test, place, 1, place, 1);
+
+ bos = kunit_kmalloc_array(test, bo_no, sizeof(*bos), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, bos);
+
+ memset(bos, 0, sizeof(*bos) * bo_no);
+ for (i = 0; i < bo_no; i++) {
+ drm_gem_private_object_init(priv->drm, &bos[i].base, bo_sizes[i]);
+ err = ttm_bo_init_reserved(priv->ttm_dev, &bos[i], bo_type, placement,
+ PAGE_SIZE, &ctx_init, NULL, NULL,
+ &dummy_ttm_bo_destroy);
+ dma_resv_unlock(bos[i].base.resv);
+ }
+
+ bo_val = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+ bo_val->type = bo_type;
+
+ ttm_bo_reserve(bo_val, false, false, NULL);
+ err = ttm_bo_validate(bo_val, placement, &ctx_val);
+ ttm_bo_unreserve(bo_val);
+
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_EXPECT_EQ(test, bos[0].resource->mem_type, mem_type_evict);
+ KUNIT_EXPECT_TRUE(test, bos[0].ttm->page_flags & TTM_TT_FLAG_ZERO_ALLOC);
+ KUNIT_EXPECT_TRUE(test, bos[0].ttm->page_flags & TTM_TT_FLAG_PRIV_POPULATED);
+ KUNIT_EXPECT_EQ(test, ctx_val.bytes_moved, small + BO_SIZE);
+ KUNIT_EXPECT_EQ(test, bos[1].resource->mem_type, mem_type);
+
+ for (i = 0; i < bo_no; i++)
+ ttm_bo_put(&bos[i]);
+ ttm_bo_put(bo_val);
+
+ ttm_mock_manager_fini(priv->ttm_dev, mem_type);
+}
+
+static void ttm_bo_validate_all_pinned_evict(struct kunit *test)
+{
+ struct ttm_test_devices *priv = test->priv;
+ struct ttm_place *place;
+ struct ttm_placement *placement;
+ struct ttm_buffer_object *bo_big, *bo_small;
+ enum ttm_bo_type bo_type = ttm_bo_type_device;
+ uint32_t mem_type = TTM_PL_VRAM;
+ struct ttm_operation_ctx ctx_init = { }, ctx_val = { };
+ int err;
+
+ ttm_mock_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE);
+
+ place = ttm_place_kunit_init(test, mem_type, 0);
+ placement = ttm_placement_kunit_init(test, place, 1, place, 1);
+
+ bo_big = kunit_kzalloc(test, sizeof(*bo_big), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, bo_big);
+
+ drm_gem_private_object_init(priv->drm, &bo_big->base, MANAGER_SIZE);
+ err = ttm_bo_init_reserved(priv->ttm_dev, bo_big, bo_type, placement,
+ PAGE_SIZE, &ctx_init, NULL, NULL,
+ &dummy_ttm_bo_destroy);
+ KUNIT_EXPECT_EQ(test, err, 0);
+
+ ttm_bo_pin(bo_big);
+ dma_resv_unlock(bo_big->base.resv);
+
+ bo_small = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+ bo_small->type = bo_type;
+
+ ttm_bo_reserve(bo_small, false, false, NULL);
+ err = ttm_bo_validate(bo_small, placement, &ctx_val);
+ ttm_bo_unreserve(bo_small);
+
+ KUNIT_EXPECT_EQ(test, err, -ENOMEM);
+
+ ttm_bo_put(bo_small);
+
+ ttm_bo_reserve(bo_big, false, false, NULL);
+ ttm_bo_unpin(bo_big);
+ dma_resv_unlock(bo_big->base.resv);
+ ttm_bo_put(bo_big);
+
+ ttm_mock_manager_fini(priv->ttm_dev, mem_type);
+}
+
+static void ttm_bo_validate_allowed_only_evict(struct kunit *test)
+{
+ struct ttm_test_devices *priv = test->priv;
+ struct ttm_place *place;
+ struct ttm_placement *placement;
+ struct ttm_buffer_object *bo, *bo_evictable, *bo_pinned;
+ enum ttm_bo_type bo_type = ttm_bo_type_device;
+ uint32_t mem_type = TTM_PL_VRAM, mem_type_evict = TTM_PL_SYSTEM;
+ struct ttm_operation_ctx ctx_init = { }, ctx_val = { };
+ uint32_t size = SZ_512K;
+ int err;
+
+ ttm_mock_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE);
+
+ place = ttm_place_kunit_init(test, mem_type, 0);
+ placement = ttm_placement_kunit_init(test, place, 1, place, 1);
+
+ bo_pinned = kunit_kzalloc(test, sizeof(*bo_pinned), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, bo_pinned);
+
+ drm_gem_private_object_init(priv->drm, &bo_pinned->base, size);
+ err = ttm_bo_init_reserved(priv->ttm_dev, bo_pinned, bo_type, placement,
+ PAGE_SIZE, &ctx_init, NULL, NULL,
+ &dummy_ttm_bo_destroy);
+ KUNIT_EXPECT_EQ(test, err, 0);
+ ttm_bo_pin(bo_pinned);
+ dma_resv_unlock(bo_pinned->base.resv);
+
+ bo_evictable = kunit_kzalloc(test, sizeof(*bo_evictable), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, bo_evictable);
+
+ drm_gem_private_object_init(priv->drm, &bo_evictable->base, size);
+ err = ttm_bo_init_reserved(priv->ttm_dev, bo_evictable, bo_type, placement,
+ PAGE_SIZE, &ctx_init, NULL, NULL,
+ &dummy_ttm_bo_destroy);
+ KUNIT_EXPECT_EQ(test, err, 0);
+ dma_resv_unlock(bo_evictable->base.resv);
+
+ bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+ bo->type = bo_type;
+
+ ttm_bo_reserve(bo, false, false, NULL);
+ err = ttm_bo_validate(bo, placement, &ctx_val);
+ ttm_bo_unreserve(bo);
+
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_EXPECT_EQ(test, bo->resource->mem_type, mem_type);
+ KUNIT_EXPECT_EQ(test, bo_pinned->resource->mem_type, mem_type);
+ KUNIT_EXPECT_EQ(test, bo_evictable->resource->mem_type, mem_type_evict);
+ KUNIT_EXPECT_EQ(test, ctx_val.bytes_moved, size + BO_SIZE);
+
+ ttm_bo_put(bo);
+ ttm_bo_put(bo_evictable);
+
+ ttm_bo_reserve(bo_pinned, false, false, NULL);
+ ttm_bo_unpin(bo_pinned);
+ dma_resv_unlock(bo_pinned->base.resv);
+ ttm_bo_put(bo_pinned);
+
+ ttm_mock_manager_fini(priv->ttm_dev, mem_type);
+}
+
+static void ttm_bo_validate_deleted_evict(struct kunit *test)
+{
+ struct ttm_test_devices *priv = test->priv;
+ struct ttm_place *place;
+ struct ttm_placement *placement;
+ struct ttm_buffer_object *bo_big, *bo_small;
+ struct ttm_resource_manager *man;
+ enum ttm_bo_type bo_type = ttm_bo_type_device;
+ uint32_t mem_type = TTM_PL_VRAM;
+ struct ttm_operation_ctx ctx_init = { }, ctx_val = { };
+ uint32_t small = SZ_8K, big = MANAGER_SIZE - BO_SIZE;
+ int err;
+
+ ttm_mock_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE);
+ man = ttm_manager_type(priv->ttm_dev, mem_type);
+
+ place = ttm_place_kunit_init(test, mem_type, 0);
+ placement = ttm_placement_kunit_init(test, place, 1, place, 1);
+
+ bo_big = kunit_kzalloc(test, sizeof(*bo_big), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, bo_big);
+
+ drm_gem_private_object_init(priv->drm, &bo_big->base, big);
+ err = ttm_bo_init_reserved(priv->ttm_dev, bo_big, bo_type, placement,
+ PAGE_SIZE, &ctx_init, NULL, NULL,
+ &dummy_ttm_bo_destroy);
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_EXPECT_EQ(test, ttm_resource_manager_usage(man), big);
+
+ dma_resv_unlock(bo_big->base.resv);
+ bo_big->deleted = true;
+
+ bo_small = ttm_bo_kunit_init(test, test->priv, small);
+ bo_small->type = bo_type;
+
+ ttm_bo_reserve(bo_small, false, false, NULL);
+ err = ttm_bo_validate(bo_small, placement, &ctx_val);
+ ttm_bo_unreserve(bo_small);
+
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_EXPECT_EQ(test, bo_small->resource->mem_type, mem_type);
+ KUNIT_EXPECT_EQ(test, ttm_resource_manager_usage(man), small);
+ KUNIT_EXPECT_NULL(test, bo_big->ttm);
+ KUNIT_EXPECT_NULL(test, bo_big->resource);
+
+ ttm_bo_put(bo_small);
+ ttm_bo_put(bo_big);
+ ttm_mock_manager_fini(priv->ttm_dev, mem_type);
+}
+
+static void ttm_bo_validate_busy_domain_evict(struct kunit *test)
+{
+ struct ttm_test_devices *priv = test->priv;
+ struct ttm_place *place;
+ struct ttm_placement *placement;
+ struct ttm_buffer_object *bo_init, *bo_val;
+ enum ttm_bo_type bo_type = ttm_bo_type_device;
+ uint32_t mem_type = TTM_PL_VRAM, mem_type_evict = TTM_PL_MOCK1;
+ struct ttm_operation_ctx ctx_init = { }, ctx_val = { };
+ int err;
+
+ /*
+ * Drop the default device and setup a new one that points to busy
+ * thus unsuitable eviction domain
+ */
+ ttm_device_fini(priv->ttm_dev);
+
+ err = ttm_device_kunit_init_bad_evict(test->priv, priv->ttm_dev, false, false);
+ KUNIT_ASSERT_EQ(test, err, 0);
+
+ ttm_mock_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE);
+ ttm_busy_manager_init(priv->ttm_dev, mem_type_evict, MANAGER_SIZE);
+
+ place = ttm_place_kunit_init(test, mem_type, 0);
+ placement = ttm_placement_kunit_init(test, place, 1, place, 1);
+
+ bo_init = kunit_kzalloc(test, sizeof(*bo_init), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, bo_init);
+
+ drm_gem_private_object_init(priv->drm, &bo_init->base, MANAGER_SIZE);
+ err = ttm_bo_init_reserved(priv->ttm_dev, bo_init, bo_type, placement,
+ PAGE_SIZE, &ctx_init, NULL, NULL,
+ &dummy_ttm_bo_destroy);
+ KUNIT_EXPECT_EQ(test, err, 0);
+ dma_resv_unlock(bo_init->base.resv);
+
+ bo_val = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+ bo_val->type = bo_type;
+
+ ttm_bo_reserve(bo_val, false, false, NULL);
+ err = ttm_bo_validate(bo_val, placement, &ctx_val);
+ ttm_bo_unreserve(bo_val);
+
+ KUNIT_EXPECT_EQ(test, err, -ENOMEM);
+ KUNIT_EXPECT_EQ(test, bo_init->resource->mem_type, mem_type);
+ KUNIT_EXPECT_NULL(test, bo_val->resource);
+
+ ttm_bo_put(bo_init);
+ ttm_bo_put(bo_val);
+
+ ttm_mock_manager_fini(priv->ttm_dev, mem_type);
+ ttm_bad_manager_fini(priv->ttm_dev, mem_type_evict);
+}
+
+static void ttm_bo_validate_evict_gutting(struct kunit *test)
+{
+ struct ttm_test_devices *priv = test->priv;
+ struct ttm_place *place;
+ struct ttm_placement *placement;
+ struct ttm_buffer_object *bo, *bo_evict;
+ enum ttm_bo_type bo_type = ttm_bo_type_device;
+ uint32_t mem_type = TTM_PL_MOCK1;
+ struct ttm_operation_ctx ctx_init = { }, ctx_val = { };
+ int err;
+
+ ttm_mock_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE);
+
+ place = ttm_place_kunit_init(test, mem_type, 0);
+ placement = ttm_placement_kunit_init(test, place, 1, place, 1);
+
+ bo_evict = kunit_kzalloc(test, sizeof(*bo_evict), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, bo_evict);
+
+ drm_gem_private_object_init(priv->drm, &bo_evict->base, MANAGER_SIZE);
+ err = ttm_bo_init_reserved(priv->ttm_dev, bo_evict, bo_type, placement,
+ PAGE_SIZE, &ctx_init, NULL, NULL,
+ &dummy_ttm_bo_destroy);
+ KUNIT_EXPECT_EQ(test, err, 0);
+ dma_resv_unlock(bo_evict->base.resv);
+
+ bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+ bo->type = bo_type;
+
+ ttm_bo_reserve(bo, false, false, NULL);
+ err = ttm_bo_validate(bo, placement, &ctx_val);
+ ttm_bo_unreserve(bo);
+
+ KUNIT_EXPECT_EQ(test, err, 0);
+ KUNIT_EXPECT_EQ(test, bo->resource->mem_type, mem_type);
+ KUNIT_ASSERT_NULL(test, bo_evict->resource);
+ KUNIT_ASSERT_TRUE(test, bo_evict->ttm->page_flags & TTM_TT_FLAG_ZERO_ALLOC);
+
+ ttm_bo_put(bo_evict);
+ ttm_bo_put(bo);
+
+ ttm_mock_manager_fini(priv->ttm_dev, mem_type);
+}
+
+static void ttm_bo_validate_recrusive_evict(struct kunit *test)
+{
+ struct ttm_test_devices *priv = test->priv;
+ struct ttm_buffer_object *bo_tt, *bo_mock, *bo_val;
+ struct ttm_place *place_tt, *place_mock;
+ struct ttm_placement *placement_tt, *placement_mock;
+ enum ttm_bo_type bo_type = ttm_bo_type_device;
+ uint32_t mem_type = TTM_PL_TT, mem_type_evict = TTM_PL_MOCK2;
+ struct ttm_operation_ctx ctx_init = { }, ctx_val = { };
+ int err;
+
+ ttm_mock_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE);
+ ttm_mock_manager_init(priv->ttm_dev, mem_type_evict, MANAGER_SIZE);
+
+ place_tt = ttm_place_kunit_init(test, mem_type, 0);
+ place_mock = ttm_place_kunit_init(test, mem_type_evict, 0);
+
+ placement_tt = ttm_placement_kunit_init(test, place_tt, 1, place_tt, 1);
+ placement_mock = ttm_placement_kunit_init(test, place_mock,
+ 1, place_mock, 1);
+
+ bo_tt = kunit_kzalloc(test, sizeof(*bo_tt), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, bo_tt);
+
+ bo_mock = kunit_kzalloc(test, sizeof(*bo_mock), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, bo_mock);
+
+ drm_gem_private_object_init(priv->drm, &bo_tt->base, MANAGER_SIZE);
+ err = ttm_bo_init_reserved(priv->ttm_dev, bo_tt, bo_type, placement_tt,
+ PAGE_SIZE, &ctx_init, NULL, NULL,
+ &dummy_ttm_bo_destroy);
+ KUNIT_EXPECT_EQ(test, err, 0);
+ dma_resv_unlock(bo_tt->base.resv);
+
+ drm_gem_private_object_init(priv->drm, &bo_mock->base, MANAGER_SIZE);
+ err = ttm_bo_init_reserved(priv->ttm_dev, bo_mock, bo_type, placement_mock,
+ PAGE_SIZE, &ctx_init, NULL, NULL,
+ &dummy_ttm_bo_destroy);
+ KUNIT_EXPECT_EQ(test, err, 0);
+ dma_resv_unlock(bo_mock->base.resv);
+
+ bo_val = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+ bo_val->type = bo_type;
+
+ ttm_bo_reserve(bo_val, false, false, NULL);
+ err = ttm_bo_validate(bo_val, placement_tt, &ctx_val);
+ ttm_bo_unreserve(bo_val);
+
+ KUNIT_EXPECT_EQ(test, err, 0);
+
+ ttm_mock_manager_fini(priv->ttm_dev, mem_type);
+ ttm_mock_manager_fini(priv->ttm_dev, mem_type_evict);
+
+ ttm_bo_put(bo_val);
+ ttm_bo_put(bo_tt);
+ ttm_bo_put(bo_mock);
+}
+
static struct kunit_case ttm_bo_validate_test_cases[] = {
KUNIT_CASE_PARAM(ttm_bo_init_reserved_sys_man, ttm_bo_types_gen_params),
KUNIT_CASE_PARAM(ttm_bo_init_reserved_mock_man, ttm_bo_types_gen_params),
@@ -777,6 +1195,14 @@ static struct kunit_case ttm_bo_validate_test_cases[] = {
KUNIT_CASE(ttm_bo_validate_move_fence_signaled),
KUNIT_CASE_PARAM(ttm_bo_validate_move_fence_not_signaled,
ttm_bo_validate_wait_gen_params),
+ KUNIT_CASE(ttm_bo_validate_swapout),
+ KUNIT_CASE(ttm_bo_validate_happy_evict),
+ KUNIT_CASE(ttm_bo_validate_all_pinned_evict),
+ KUNIT_CASE(ttm_bo_validate_allowed_only_evict),
+ KUNIT_CASE(ttm_bo_validate_deleted_evict),
+ KUNIT_CASE(ttm_bo_validate_busy_domain_evict),
+ KUNIT_CASE(ttm_bo_validate_evict_gutting),
+ KUNIT_CASE(ttm_bo_validate_recrusive_evict),
{}
};
diff --git a/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c b/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c
index 719c1d56388e..1be537fc6af3 100644
--- a/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c
+++ b/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c
@@ -6,6 +6,48 @@
#include "ttm_kunit_helpers.h"
+static const struct ttm_place sys_place = {
+ .fpfn = 0,
+ .lpfn = 0,
+ .mem_type = TTM_PL_SYSTEM,
+ .flags = 0,
+};
+
+static const struct ttm_place mock1_place = {
+ .fpfn = 0,
+ .lpfn = 0,
+ .mem_type = TTM_PL_MOCK1,
+ .flags = 0,
+};
+
+static const struct ttm_place mock2_place = {
+ .fpfn = 0,
+ .lpfn = 0,
+ .mem_type = TTM_PL_MOCK2,
+ .flags = 0,
+};
+
+static struct ttm_placement sys_placement = {
+ .num_placement = 1,
+ .placement = &sys_place,
+ .num_busy_placement = 1,
+ .busy_placement = &sys_place,
+};
+
+static struct ttm_placement bad_placement = {
+ .num_placement = 1,
+ .placement = &mock1_place,
+ .num_busy_placement = 1,
+ .busy_placement = &mock1_place,
+};
+
+static struct ttm_placement mock_placement = {
+ .num_placement = 1,
+ .placement = &mock2_place,
+ .num_busy_placement = 1,
+ .busy_placement = &mock2_place,
+};
+
static struct ttm_tt *ttm_tt_simple_create(struct ttm_buffer_object *bo,
uint32_t page_flags)
{
@@ -66,10 +108,53 @@ static int mock_move(struct ttm_buffer_object *bo, bool evict,
return ttm_bo_move_memcpy(bo, ctx, new_mem);
}
+static void mock_evict_flags(struct ttm_buffer_object *bo,
+ struct ttm_placement *placement)
+{
+ switch (bo->resource->mem_type) {
+ case TTM_PL_VRAM:
+ case TTM_PL_SYSTEM:
+ case TTM_PL_MULTIHOP:
+ *placement = sys_placement;
+ break;
+ case TTM_PL_TT:
+ *placement = mock_placement;
+ break;
+ case TTM_PL_MOCK1:
+ /* Purge objects coming from this domain */
+ break;
+ }
+}
+
+static void bad_evict_flags(struct ttm_buffer_object *bo,
+ struct ttm_placement *placement)
+{
+ *placement = bad_placement;
+}
+
+static int ttm_device_kunit_init_with_funcs(struct ttm_test_devices *priv,
+ struct ttm_device *ttm,
+ bool use_dma_alloc,
+ bool use_dma32,
+ struct ttm_device_funcs *funcs)
+{
+ struct drm_device *drm = priv->drm;
+ int err;
+
+ err = ttm_device_init(ttm, funcs, drm->dev,
+ drm->anon_inode->i_mapping,
+ drm->vma_offset_manager,
+ use_dma_alloc, use_dma32);
+
+ return err;
+}
+
struct ttm_device_funcs ttm_dev_funcs = {
.ttm_tt_create = ttm_tt_simple_create,
.ttm_tt_destroy = ttm_tt_simple_destroy,
.move = mock_move,
+ .eviction_valuable = ttm_bo_eviction_valuable,
+ .evict_flags = mock_evict_flags,
};
EXPORT_SYMBOL_GPL(ttm_dev_funcs);
@@ -78,17 +163,29 @@ int ttm_device_kunit_init(struct ttm_test_devices *priv,
bool use_dma_alloc,
bool use_dma32)
{
- struct drm_device *drm = priv->drm;
- int err;
+ return ttm_device_kunit_init_with_funcs(priv, ttm, use_dma_alloc,
+ use_dma32, &ttm_dev_funcs);
+}
+EXPORT_SYMBOL_GPL(ttm_device_kunit_init);
- err = ttm_device_init(ttm, &ttm_dev_funcs, drm->dev,
- drm->anon_inode->i_mapping,
- drm->vma_offset_manager,
- use_dma_alloc, use_dma32);
+struct ttm_device_funcs ttm_dev_funcs_bad_evict = {
+ .ttm_tt_create = ttm_tt_simple_create,
+ .ttm_tt_destroy = ttm_tt_simple_destroy,
+ .move = mock_move,
+ .eviction_valuable = ttm_bo_eviction_valuable,
+ .evict_flags = bad_evict_flags,
+};
+EXPORT_SYMBOL_GPL(ttm_dev_funcs_bad_evict);
- return err;
+int ttm_device_kunit_init_bad_evict(struct ttm_test_devices *priv,
+ struct ttm_device *ttm,
+ bool use_dma_alloc,
+ bool use_dma32)
+{
+ return ttm_device_kunit_init_with_funcs(priv, ttm, use_dma_alloc,
+ use_dma32, &ttm_dev_funcs_bad_evict);
}
-EXPORT_SYMBOL_GPL(ttm_device_kunit_init);
+EXPORT_SYMBOL_GPL(ttm_device_kunit_init_bad_evict);
struct ttm_buffer_object *ttm_bo_kunit_init(struct kunit *test,
struct ttm_test_devices *devs,
diff --git a/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.h b/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.h
index a8977eb606e5..977c4605ee4e 100644
--- a/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.h
+++ b/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.h
@@ -14,8 +14,11 @@
#include <kunit/test.h>
#define TTM_PL_MULTIHOP (TTM_PL_PRIV + 1)
+#define TTM_PL_MOCK1 (TTM_PL_PRIV + 2)
+#define TTM_PL_MOCK2 (TTM_PL_PRIV + 3)
extern struct ttm_device_funcs ttm_dev_funcs;
+extern struct ttm_device_funcs ttm_dev_funcs_bad_evict;
struct ttm_test_devices {
struct drm_device *drm;
@@ -28,6 +31,10 @@ int ttm_device_kunit_init(struct ttm_test_devices *priv,
struct ttm_device *ttm,
bool use_dma_alloc,
bool use_dma32);
+int ttm_device_kunit_init_bad_evict(struct ttm_test_devices *priv,
+ struct ttm_device *ttm,
+ bool use_dma_alloc,
+ bool use_dma32);
struct ttm_buffer_object *ttm_bo_kunit_init(struct kunit *test,
struct ttm_test_devices *devs,
size_t size);
diff --git a/drivers/gpu/drm/ttm/tests/ttm_mock_manager.c b/drivers/gpu/drm/ttm/tests/ttm_mock_manager.c
index 21636b96ac38..4dffb3c274da 100644
--- a/drivers/gpu/drm/ttm/tests/ttm_mock_manager.c
+++ b/drivers/gpu/drm/ttm/tests/ttm_mock_manager.c
@@ -153,6 +153,14 @@ static int ttm_bad_manager_alloc(struct ttm_resource_manager *man,
return -ENOSPC;
}
+static int ttm_busy_manager_alloc(struct ttm_resource_manager *man,
+ struct ttm_buffer_object *bo,
+ const struct ttm_place *place,
+ struct ttm_resource **res)
+{
+ return -EBUSY;
+}
+
static void ttm_bad_manager_free(struct ttm_resource_manager *man,
struct ttm_resource *res)
{
@@ -172,6 +180,12 @@ static const struct ttm_resource_manager_func ttm_bad_manager_funcs = {
.compatible = ttm_bad_manager_compatible
};
+static const struct ttm_resource_manager_func ttm_bad_busy_manager_funcs = {
+ .alloc = ttm_busy_manager_alloc,
+ .free = ttm_bad_manager_free,
+ .compatible = ttm_bad_manager_compatible
+};
+
int ttm_bad_manager_init(struct ttm_device *bdev, uint32_t mem_type,
uint32_t size)
{
@@ -191,6 +205,20 @@ int ttm_bad_manager_init(struct ttm_device *bdev, uint32_t mem_type,
}
EXPORT_SYMBOL_GPL(ttm_bad_manager_init);
+int ttm_busy_manager_init(struct ttm_device *bdev, uint32_t mem_type,
+ uint32_t size)
+{
+ struct ttm_resource_manager *man;
+
+ ttm_bad_manager_init(bdev, mem_type, size);
+ man = ttm_manager_type(bdev, mem_type);
+
+ man->func = &ttm_bad_busy_manager_funcs;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ttm_busy_manager_init);
+
void ttm_bad_manager_fini(struct ttm_device *bdev, uint32_t mem_type)
{
struct ttm_resource_manager *man;
diff --git a/drivers/gpu/drm/ttm/tests/ttm_mock_manager.h b/drivers/gpu/drm/ttm/tests/ttm_mock_manager.h
index d2db9de9d876..7a12d73fdc07 100644
--- a/drivers/gpu/drm/ttm/tests/ttm_mock_manager.h
+++ b/drivers/gpu/drm/ttm/tests/ttm_mock_manager.h
@@ -25,6 +25,8 @@ int ttm_mock_manager_init(struct ttm_device *bdev, uint32_t mem_type,
uint32_t size);
int ttm_bad_manager_init(struct ttm_device *bdev, uint32_t mem_type,
uint32_t size);
+int ttm_busy_manager_init(struct ttm_device *bdev, uint32_t mem_type,
+ uint32_t size);
void ttm_mock_manager_fini(struct ttm_device *bdev, uint32_t mem_type);
void ttm_bad_manager_fini(struct ttm_device *bdev, uint32_t mem_type);
--
2.34.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH RESEND v9 7/8] drm/ttm/tests: Add tests for ttm_tt_populate
2024-01-11 10:28 [PATCH RESEND v9 0/8] Improve test coverage of TTM Karolina Stolarek
` (5 preceding siblings ...)
2024-01-11 10:28 ` [PATCH RESEND v9 6/8] drm/ttm/tests: Add eviction testing Karolina Stolarek
@ 2024-01-11 10:28 ` Karolina Stolarek
2024-01-11 10:28 ` [PATCH RESEND v9 8/8] drm/ttm/tests: Add TODO file Karolina Stolarek
7 siblings, 0 replies; 12+ messages in thread
From: Karolina Stolarek @ 2024-01-11 10:28 UTC (permalink / raw)
To: dri-devel
Cc: Amaranath Somalapuram, Karolina Stolarek, Christian König,
Andi Shyti
Add tests for functions that add and release pages to TTs. Test the
swapin operation. Export ttm_tt_unpopulate, ttm_tt_swapin and
ttm_tt_swapout symbols for testing purposes.
Signed-off-by: Karolina Stolarek <karolina.stolarek@intel.com>
---
drivers/gpu/drm/ttm/tests/ttm_tt_test.c | 119 ++++++++++++++++++++++++
drivers/gpu/drm/ttm/ttm_tt.c | 3 +
2 files changed, 122 insertions(+)
diff --git a/drivers/gpu/drm/ttm/tests/ttm_tt_test.c b/drivers/gpu/drm/ttm/tests/ttm_tt_test.c
index a33a426a814d..b626228124aa 100644
--- a/drivers/gpu/drm/ttm/tests/ttm_tt_test.c
+++ b/drivers/gpu/drm/ttm/tests/ttm_tt_test.c
@@ -256,6 +256,120 @@ static void ttm_tt_destroy_basic(struct kunit *test)
ttm_tt_destroy(devs->ttm_dev, bo->ttm);
}
+static void ttm_tt_populate_null_ttm(struct kunit *test)
+{
+ const struct ttm_test_devices *devs = test->priv;
+ struct ttm_operation_ctx ctx = { };
+ int err;
+
+ err = ttm_tt_populate(devs->ttm_dev, NULL, &ctx);
+ KUNIT_ASSERT_EQ(test, err, -EINVAL);
+}
+
+static void ttm_tt_populate_populated_ttm(struct kunit *test)
+{
+ const struct ttm_test_devices *devs = test->priv;
+ struct ttm_operation_ctx ctx = { };
+ struct ttm_buffer_object *bo;
+ struct ttm_tt *tt;
+ struct page *populated_page;
+ int err;
+
+ bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+
+ tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, tt);
+
+ err = ttm_tt_init(tt, bo, 0, ttm_cached, 0);
+ KUNIT_ASSERT_EQ(test, err, 0);
+
+ err = ttm_tt_populate(devs->ttm_dev, tt, &ctx);
+ KUNIT_ASSERT_EQ(test, err, 0);
+ populated_page = *tt->pages;
+
+ err = ttm_tt_populate(devs->ttm_dev, tt, &ctx);
+ KUNIT_ASSERT_PTR_EQ(test, populated_page, *tt->pages);
+}
+
+static void ttm_tt_unpopulate_basic(struct kunit *test)
+{
+ const struct ttm_test_devices *devs = test->priv;
+ struct ttm_operation_ctx ctx = { };
+ struct ttm_buffer_object *bo;
+ struct ttm_tt *tt;
+ int err;
+
+ bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+
+ tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, tt);
+
+ err = ttm_tt_init(tt, bo, 0, ttm_cached, 0);
+ KUNIT_ASSERT_EQ(test, err, 0);
+
+ err = ttm_tt_populate(devs->ttm_dev, tt, &ctx);
+ KUNIT_ASSERT_EQ(test, err, 0);
+ KUNIT_ASSERT_TRUE(test, ttm_tt_is_populated(tt));
+
+ ttm_tt_unpopulate(devs->ttm_dev, tt);
+ KUNIT_ASSERT_FALSE(test, ttm_tt_is_populated(tt));
+}
+
+static void ttm_tt_unpopulate_empty_ttm(struct kunit *test)
+{
+ const struct ttm_test_devices *devs = test->priv;
+ struct ttm_buffer_object *bo;
+ struct ttm_tt *tt;
+ int err;
+
+ bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+
+ tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, tt);
+
+ err = ttm_tt_init(tt, bo, 0, ttm_cached, 0);
+ KUNIT_ASSERT_EQ(test, err, 0);
+
+ ttm_tt_unpopulate(devs->ttm_dev, tt);
+ /* Expect graceful handling of unpopulated TTs */
+}
+
+static void ttm_tt_swapin_basic(struct kunit *test)
+{
+ const struct ttm_test_devices *devs = test->priv;
+ int expected_num_pages = BO_SIZE >> PAGE_SHIFT;
+ struct ttm_operation_ctx ctx = { };
+ struct ttm_buffer_object *bo;
+ struct ttm_tt *tt;
+ int err, num_pages;
+
+ bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+
+ tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, tt);
+
+ err = ttm_tt_init(tt, bo, 0, ttm_cached, 0);
+ KUNIT_ASSERT_EQ(test, err, 0);
+
+ err = ttm_tt_populate(devs->ttm_dev, tt, &ctx);
+ KUNIT_ASSERT_EQ(test, err, 0);
+ KUNIT_ASSERT_TRUE(test, ttm_tt_is_populated(tt));
+
+ num_pages = ttm_tt_swapout(devs->ttm_dev, tt, GFP_KERNEL);
+ KUNIT_ASSERT_EQ(test, num_pages, expected_num_pages);
+ KUNIT_ASSERT_NOT_NULL(test, tt->swap_storage);
+ KUNIT_ASSERT_TRUE(test, tt->page_flags & TTM_TT_FLAG_SWAPPED);
+
+ /* Swapout depopulates TT, allocate pages and then swap them in */
+ err = ttm_pool_alloc(&devs->ttm_dev->pool, tt, &ctx);
+ KUNIT_ASSERT_EQ(test, err, 0);
+
+ err = ttm_tt_swapin(tt);
+ KUNIT_ASSERT_EQ(test, err, 0);
+ KUNIT_ASSERT_NULL(test, tt->swap_storage);
+ KUNIT_ASSERT_FALSE(test, tt->page_flags & TTM_TT_FLAG_SWAPPED);
+}
+
static struct kunit_case ttm_tt_test_cases[] = {
KUNIT_CASE_PARAM(ttm_tt_init_basic, ttm_tt_init_basic_gen_params),
KUNIT_CASE(ttm_tt_init_misaligned),
@@ -267,6 +381,11 @@ static struct kunit_case ttm_tt_test_cases[] = {
KUNIT_CASE(ttm_tt_create_ttm_exists),
KUNIT_CASE(ttm_tt_create_failed),
KUNIT_CASE(ttm_tt_destroy_basic),
+ KUNIT_CASE(ttm_tt_populate_null_ttm),
+ KUNIT_CASE(ttm_tt_populate_populated_ttm),
+ KUNIT_CASE(ttm_tt_unpopulate_basic),
+ KUNIT_CASE(ttm_tt_unpopulate_empty_ttm),
+ KUNIT_CASE(ttm_tt_swapin_basic),
{}
};
diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c
index d978dc539a9b..0c7af842007f 100644
--- a/drivers/gpu/drm/ttm/ttm_tt.c
+++ b/drivers/gpu/drm/ttm/ttm_tt.c
@@ -238,6 +238,7 @@ int ttm_tt_swapin(struct ttm_tt *ttm)
out_err:
return ret;
}
+EXPORT_SYMBOL_FOR_TESTS_ONLY(ttm_tt_swapin);
/**
* ttm_tt_swapout - swap out tt object
@@ -295,6 +296,7 @@ int ttm_tt_swapout(struct ttm_device *bdev, struct ttm_tt *ttm,
return ret;
}
+EXPORT_SYMBOL_FOR_TESTS_ONLY(ttm_tt_swapout);
int ttm_tt_populate(struct ttm_device *bdev,
struct ttm_tt *ttm, struct ttm_operation_ctx *ctx)
@@ -373,6 +375,7 @@ void ttm_tt_unpopulate(struct ttm_device *bdev, struct ttm_tt *ttm)
ttm->page_flags &= ~TTM_TT_FLAG_PRIV_POPULATED;
}
+EXPORT_SYMBOL_FOR_TESTS_ONLY(ttm_tt_unpopulate);
#ifdef CONFIG_DEBUG_FS
--
2.34.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH RESEND v9 8/8] drm/ttm/tests: Add TODO file
2024-01-11 10:28 [PATCH RESEND v9 0/8] Improve test coverage of TTM Karolina Stolarek
` (6 preceding siblings ...)
2024-01-11 10:28 ` [PATCH RESEND v9 7/8] drm/ttm/tests: Add tests for ttm_tt_populate Karolina Stolarek
@ 2024-01-11 10:28 ` Karolina Stolarek
7 siblings, 0 replies; 12+ messages in thread
From: Karolina Stolarek @ 2024-01-11 10:28 UTC (permalink / raw)
To: dri-devel
Cc: Amaranath Somalapuram, Karolina Stolarek, Christian König,
Andi Shyti
List improvements for the test suite with some notes.
Signed-off-by: Karolina Stolarek <karolina.stolarek@intel.com>
---
drivers/gpu/drm/ttm/tests/TODO | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
create mode 100644 drivers/gpu/drm/ttm/tests/TODO
diff --git a/drivers/gpu/drm/ttm/tests/TODO b/drivers/gpu/drm/ttm/tests/TODO
new file mode 100644
index 000000000000..3095c3225cec
--- /dev/null
+++ b/drivers/gpu/drm/ttm/tests/TODO
@@ -0,0 +1,24 @@
+TODO
+=====
+
+- Add a test case where the only evictable BO is busy
+- Add tests for ttm_bo_vm_ops (that includes ttm_bo_kmap() testing)
+- Update eviction tests so they use parametrized "from" memory type
+- Improve mock manager's implementation, e.g. allocate a block of
+ dummy memory that can be used when testing page mapping functions
+- Suggestion: Add test cases with external BOs
+- Suggestion: randomize the number and size of tested buffers in
+ ttm_bo_validate()
+- Agree on the naming convention
+
+Notes and gotchas
+=================
+
+- We want to stick to running UML to provide hardware-independent testing
+- Triggering ttm_bo_vm_ops callbacks from KUnit (i.e. kernel) might be
+ a challenge, but it seems doable. Use selftests like
+ i915/gem/selftests/i915_gem_mman.c for inspiration
+- The test suite uses UML, so ioremap() returns NULL. Simply switching
+ to x86 won't solve the issue, because we also get NULL when trying to
+ remap RAM. This means that we can only test a part of ttm_bo_ioremap()
+ (helper called in ttm_bo_kmap() function)
--
2.34.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH RESEND v9 1/8] drm/ttm/tests: Fix argument in ttm_tt_kunit_init()
2024-01-11 10:28 ` [PATCH RESEND v9 1/8] drm/ttm/tests: Fix argument in ttm_tt_kunit_init() Karolina Stolarek
@ 2024-01-11 14:59 ` Christian König
2024-01-11 15:54 ` Karolina Stolarek
2024-01-15 11:56 ` Somalapuram, Amaranath
0 siblings, 2 replies; 12+ messages in thread
From: Christian König @ 2024-01-11 14:59 UTC (permalink / raw)
To: Karolina Stolarek, dri-devel
Cc: Amaranath Somalapuram, Andi Shyti, Dominik Karol Piątkowski
I've gone ahead and pushed this one to drm-misc-next.
Going to take a look at the rest as well.
@Amar could you run another test round with those? And maybe ping Kenny
if we can integrate them into the CI.
Thanks,
Christian.
Am 11.01.24 um 11:28 schrieb Karolina Stolarek:
> Remove a leftover definition of page order and pass an empty flag value
> in ttm_pool_pre_populated().
>
> Signed-off-by: Karolina Stolarek <karolina.stolarek@intel.com>
> Tested-by: Amaranath Somalapuram <Amaranath.Somalapuram@amd.com>
> Reviewed-by: Dominik Karol Piątkowski <dominik.karol.piatkowski@intel.com>
> Acked-by: Christian König <christian.koenig@amd.com>
> ---
> drivers/gpu/drm/ttm/tests/ttm_pool_test.c | 3 +--
> 1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/ttm/tests/ttm_pool_test.c b/drivers/gpu/drm/ttm/tests/ttm_pool_test.c
> index 2d9cae8cd984..b97f7b6daf5b 100644
> --- a/drivers/gpu/drm/ttm/tests/ttm_pool_test.c
> +++ b/drivers/gpu/drm/ttm/tests/ttm_pool_test.c
> @@ -78,10 +78,9 @@ static struct ttm_pool *ttm_pool_pre_populated(struct kunit *test,
> struct ttm_test_devices *devs = priv->devs;
> struct ttm_pool *pool;
> struct ttm_tt *tt;
> - unsigned long order = __fls(size / PAGE_SIZE);
> int err;
>
> - tt = ttm_tt_kunit_init(test, order, caching, size);
> + tt = ttm_tt_kunit_init(test, 0, caching, size);
> KUNIT_ASSERT_NOT_NULL(test, tt);
>
> pool = kunit_kzalloc(test, sizeof(*pool), GFP_KERNEL);
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH RESEND v9 1/8] drm/ttm/tests: Fix argument in ttm_tt_kunit_init()
2024-01-11 14:59 ` Christian König
@ 2024-01-11 15:54 ` Karolina Stolarek
2024-01-15 11:56 ` Somalapuram, Amaranath
1 sibling, 0 replies; 12+ messages in thread
From: Karolina Stolarek @ 2024-01-11 15:54 UTC (permalink / raw)
To: Christian König, dri-devel
Cc: Amaranath Somalapuram, Andi Shyti, Dominik Karol Piątkowski
On 11.01.2024 15:59, Christian König wrote:
> I've gone ahead and pushed this one to drm-misc-next.
>
> Going to take a look at the rest as well.
Awesome, thanks a lot!
All the best,
Karolina
>
> @Amar could you run another test round with those? And maybe ping Kenny
> if we can integrate them into the CI.
>
> Thanks,
> Christian.
>
> Am 11.01.24 um 11:28 schrieb Karolina Stolarek:
>> Remove a leftover definition of page order and pass an empty flag value
>> in ttm_pool_pre_populated().
>>
>> Signed-off-by: Karolina Stolarek <karolina.stolarek@intel.com>
>> Tested-by: Amaranath Somalapuram <Amaranath.Somalapuram@amd.com>
>> Reviewed-by: Dominik Karol Piątkowski
>> <dominik.karol.piatkowski@intel.com>
>> Acked-by: Christian König <christian.koenig@amd.com>
>> ---
>> drivers/gpu/drm/ttm/tests/ttm_pool_test.c | 3 +--
>> 1 file changed, 1 insertion(+), 2 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/ttm/tests/ttm_pool_test.c
>> b/drivers/gpu/drm/ttm/tests/ttm_pool_test.c
>> index 2d9cae8cd984..b97f7b6daf5b 100644
>> --- a/drivers/gpu/drm/ttm/tests/ttm_pool_test.c
>> +++ b/drivers/gpu/drm/ttm/tests/ttm_pool_test.c
>> @@ -78,10 +78,9 @@ static struct ttm_pool
>> *ttm_pool_pre_populated(struct kunit *test,
>> struct ttm_test_devices *devs = priv->devs;
>> struct ttm_pool *pool;
>> struct ttm_tt *tt;
>> - unsigned long order = __fls(size / PAGE_SIZE);
>> int err;
>> - tt = ttm_tt_kunit_init(test, order, caching, size);
>> + tt = ttm_tt_kunit_init(test, 0, caching, size);
>> KUNIT_ASSERT_NOT_NULL(test, tt);
>> pool = kunit_kzalloc(test, sizeof(*pool), GFP_KERNEL);
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH RESEND v9 1/8] drm/ttm/tests: Fix argument in ttm_tt_kunit_init()
2024-01-11 14:59 ` Christian König
2024-01-11 15:54 ` Karolina Stolarek
@ 2024-01-15 11:56 ` Somalapuram, Amaranath
1 sibling, 0 replies; 12+ messages in thread
From: Somalapuram, Amaranath @ 2024-01-15 11:56 UTC (permalink / raw)
To: Christian König, Karolina Stolarek, dri-devel
Cc: Amaranath Somalapuram, Andi Shyti, Dominik Karol Piątkowski
On 1/11/2024 8:29 PM, Christian König wrote:
> I've gone ahead and pushed this one to drm-misc-next.
>
> Going to take a look at the rest as well.
>
> @Amar could you run another test round with those? And maybe ping
> Kenny if we can integrate them into the CI.
>
> Thanks,
> Christian.
>
Look's good:
Regards,
S.Amarnath
rtg@rtg-Artic:~/amar/git/drm-misc$ ./tools/testing/kunit/kunit.py run
--kunitconfig=drivers/gpu/drm/ttm/tests
[17:21:52] Configuring KUnit Kernel ...
Regenerating .config ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
[17:21:55] Building KUnit Kernel ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
Building with:
$ make ARCH=um O=.kunit --jobs=16
[17:22:23] Starting KUnit Kernel (1/1)...
[17:22:23] ============================================================
[17:22:23] ======================= ttm_device ========================
[17:22:23] [PASSED] ttm_device_init_basic
[17:22:23] [PASSED] ttm_device_init_multiple
[17:22:23] [PASSED] ttm_device_fini_basic
[17:22:23] [PASSED] ttm_device_init_no_vma_man
[17:22:23] ================== ttm_device_init_pools ==================
[17:22:23] [PASSED] No DMA allocations, no DMA32 required
[17:22:23] [PASSED] DMA allocations, DMA32 required
[17:22:23] [PASSED] No DMA allocations, DMA32 required
[17:22:23] [PASSED] DMA allocations, no DMA32 required
[17:22:23] ============== [PASSED] ttm_device_init_pools ==============
[17:22:23] =================== [PASSED] ttm_device ====================
[17:22:23] ======================== ttm_pool =========================
[17:22:23] ================== ttm_pool_alloc_basic ===================
[17:22:23] [PASSED] One page
[17:22:23] [PASSED] More than one page
[17:22:23] [PASSED] Above the allocation limit
[17:22:23] [PASSED] One page, with coherent DMA mappings enabled
[17:22:23] [PASSED] Above the allocation limit, with coherent DMA
mappings enabled
[17:22:23] ============== [PASSED] ttm_pool_alloc_basic ===============
[17:22:23] ============== ttm_pool_alloc_basic_dma_addr ==============
[17:22:23] [PASSED] One page
[17:22:23] [PASSED] More than one page
[17:22:23] [PASSED] Above the allocation limit
[17:22:23] [PASSED] One page, with coherent DMA mappings enabled
[17:22:23] [PASSED] Above the allocation limit, with coherent DMA
mappings enabled
[17:22:23] ========== [PASSED] ttm_pool_alloc_basic_dma_addr ==========
[17:22:23] [PASSED] ttm_pool_alloc_order_caching_match
[17:22:23] [PASSED] ttm_pool_alloc_caching_mismatch
[17:22:23] [PASSED] ttm_pool_alloc_order_mismatch
[17:22:23] [PASSED] ttm_pool_free_dma_alloc
[17:22:23] [PASSED] ttm_pool_free_no_dma_alloc
[17:22:23] [PASSED] ttm_pool_fini_basic
[17:22:23] ==================== [PASSED] ttm_pool =====================
[17:22:23] ====================== ttm_resource =======================
[17:22:23] ================= ttm_resource_init_basic =================
[17:22:23] [PASSED] Init resource in TTM_PL_SYSTEM
[17:22:23] [PASSED] Init resource in TTM_PL_VRAM
[17:22:23] [PASSED] Init resource in a private placement
[17:22:23] [PASSED] Init resource in TTM_PL_SYSTEM, set placement flags
[17:22:23] ============= [PASSED] ttm_resource_init_basic =============
[17:22:23] [PASSED] ttm_resource_init_pinned
[17:22:23] [PASSED] ttm_resource_fini_basic
[17:22:23] [PASSED] ttm_resource_manager_init_basic
[17:22:23] [PASSED] ttm_resource_manager_usage_basic
[17:22:23] [PASSED] ttm_resource_manager_set_used_basic
[17:22:23] [PASSED] ttm_sys_man_alloc_basic
[17:22:23] [PASSED] ttm_sys_man_free_basic
[17:22:23] ================== [PASSED] ttm_resource ===================
[17:22:23] ========================= ttm_tt ==========================
[17:22:23] ==================== ttm_tt_init_basic ====================
[17:22:23] [PASSED] Page-aligned size
[17:22:23] [PASSED] Extra pages requested
[17:22:23] ================ [PASSED] ttm_tt_init_basic ================
[17:22:23] [PASSED] ttm_tt_init_misaligned
[17:22:23] [PASSED] ttm_tt_fini_basic
[17:22:23] [PASSED] ttm_tt_fini_sg
[17:22:23] [PASSED] ttm_tt_fini_shmem
[17:22:23] [PASSED] ttm_tt_create_basic
[17:22:23] [PASSED] ttm_tt_create_invalid_bo_type
[17:22:23] [PASSED] ttm_tt_create_ttm_exists
[17:22:23] [PASSED] ttm_tt_create_failed
[17:22:23] [PASSED] ttm_tt_destroy_basic
[17:22:23] [PASSED] ttm_tt_populate_null_ttm
[17:22:23] [PASSED] ttm_tt_populate_populated_ttm
[17:22:23] [PASSED] ttm_tt_unpopulate_basic
[17:22:23] [PASSED] ttm_tt_unpopulate_empty_ttm
[17:22:23] [PASSED] ttm_tt_swapin_basic
[17:22:23] ===================== [PASSED] ttm_tt ======================
[17:22:23] ========================= ttm_bo ==========================
[17:22:23] =========== ttm_bo_reserve_optimistic_no_ticket ===========
[17:22:23] [PASSED] Cannot be interrupted and sleeps
[17:22:23] [PASSED] Cannot be interrupted, locks straight away
[17:22:23] [PASSED] Can be interrupted, sleeps
[17:22:23] ======= [PASSED] ttm_bo_reserve_optimistic_no_ticket =======
[17:22:23] [PASSED] ttm_bo_reserve_locked_no_sleep
[17:22:23] [PASSED] ttm_bo_reserve_no_wait_ticket
[17:22:23] [PASSED] ttm_bo_reserve_double_resv
[17:22:23] [PASSED] ttm_bo_reserve_interrupted
[17:22:23] [PASSED] ttm_bo_reserve_deadlock
[17:22:23] [PASSED] ttm_bo_unreserve_basic
[17:22:23] [PASSED] ttm_bo_unreserve_pinned
[17:22:23] [PASSED] ttm_bo_unreserve_bulk
[17:22:23] [PASSED] ttm_bo_put_basic
[17:22:23] [PASSED] ttm_bo_put_shared_resv
[17:22:23] [PASSED] ttm_bo_pin_basic
[17:22:23] [PASSED] ttm_bo_pin_unpin_resource
[17:22:23] [PASSED] ttm_bo_multiple_pin_one_unpin
[17:22:23] ===================== [PASSED] ttm_bo ======================
[17:22:23] ===================== ttm_bo_validate =====================
[17:22:23] ============== ttm_bo_init_reserved_sys_man ===============
[17:22:23] [PASSED] Buffer object for userspace
[17:22:23] [PASSED] Kernel buffer object
[17:22:23] [PASSED] Shared buffer object
[17:22:23] ========== [PASSED] ttm_bo_init_reserved_sys_man ===========
[17:22:23] ============== ttm_bo_init_reserved_mock_man ==============
[17:22:23] [PASSED] Buffer object for userspace
[17:22:23] [PASSED] Kernel buffer object
[17:22:23] [PASSED] Shared buffer object
[17:22:23] ========== [PASSED] ttm_bo_init_reserved_mock_man ==========
[17:22:23] [PASSED] ttm_bo_init_reserved_resv
[17:22:23] ================== ttm_bo_validate_basic ==================
[17:22:23] [PASSED] Buffer object for userspace
[17:22:23] [PASSED] Kernel buffer object
[17:22:23] [PASSED] Shared buffer object
[17:22:23] ============== [PASSED] ttm_bo_validate_basic ==============
[17:22:23] [PASSED] ttm_bo_validate_invalid_placement
[17:22:23] ============= ttm_bo_validate_same_placement ==============
[17:22:23] [PASSED] System manager
[17:22:23] [PASSED] VRAM manager
[17:22:23] ========= [PASSED] ttm_bo_validate_same_placement ==========
[17:22:23] [PASSED] ttm_bo_validate_failed_alloc
[17:22:23] [PASSED] ttm_bo_validate_pinned
[17:22:23] [PASSED] ttm_bo_validate_busy_placement
[17:22:23] ================ ttm_bo_validate_multihop =================
[17:22:23] [PASSED] Buffer object for userspace
[17:22:23] [PASSED] Kernel buffer object
[17:22:23] [PASSED] Shared buffer object
[17:22:23] ============ [PASSED] ttm_bo_validate_multihop =============
[17:22:23] ========== ttm_bo_validate_no_placement_signaled ==========
[17:22:23] [PASSED] Buffer object in system domain, no page vector
[17:22:23] [PASSED] Buffer object in system domain with an existing page
vector
[17:22:23] ====== [PASSED] ttm_bo_validate_no_placement_signaled ======
[17:22:23] ======== ttm_bo_validate_no_placement_not_signaled ========
[17:22:23] [PASSED] Buffer object for userspace
[17:22:23] [PASSED] Kernel buffer object
[17:22:23] [PASSED] Shared buffer object
[17:22:23] ==== [PASSED] ttm_bo_validate_no_placement_not_signaled ====
[17:22:23] [PASSED] ttm_bo_validate_move_fence_signaled
[17:22:24] ========= ttm_bo_validate_move_fence_not_signaled =========
[17:22:24] [PASSED] Waits for GPU
[17:22:24] [PASSED] Tries to lock straight away
[17:22:24] ===== [PASSED] ttm_bo_validate_move_fence_not_signaled =====
[17:22:24] [PASSED] ttm_bo_validate_swapout
[17:22:24] [PASSED] ttm_bo_validate_happy_evict
[17:22:24] [PASSED] ttm_bo_validate_all_pinned_evict
[17:22:24] [PASSED] ttm_bo_validate_allowed_only_evict
[17:22:24] [PASSED] ttm_bo_validate_deleted_evict
[17:22:24] [PASSED] ttm_bo_validate_busy_domain_evict
[17:22:24] [PASSED] ttm_bo_validate_evict_gutting
[17:22:24] [PASSED] ttm_bo_validate_recrusive_evict
[17:22:24] ================= [PASSED] ttm_bo_validate =================
[17:22:24] ============================================================
[17:22:24] Testing complete. Ran 102 tests: passed: 102
[17:22:24] Elapsed time: 31.810s total, 2.810s configuring, 28.277s
building, 0.563s running
> Am 11.01.24 um 11:28 schrieb Karolina Stolarek:
>> Remove a leftover definition of page order and pass an empty flag value
>> in ttm_pool_pre_populated().
>>
>> Signed-off-by: Karolina Stolarek <karolina.stolarek@intel.com>
>> Tested-by: Amaranath Somalapuram <Amaranath.Somalapuram@amd.com>
>> Reviewed-by: Dominik Karol Piątkowski
>> <dominik.karol.piatkowski@intel.com>
>> Acked-by: Christian König <christian.koenig@amd.com>
>> ---
>> drivers/gpu/drm/ttm/tests/ttm_pool_test.c | 3 +--
>> 1 file changed, 1 insertion(+), 2 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/ttm/tests/ttm_pool_test.c
>> b/drivers/gpu/drm/ttm/tests/ttm_pool_test.c
>> index 2d9cae8cd984..b97f7b6daf5b 100644
>> --- a/drivers/gpu/drm/ttm/tests/ttm_pool_test.c
>> +++ b/drivers/gpu/drm/ttm/tests/ttm_pool_test.c
>> @@ -78,10 +78,9 @@ static struct ttm_pool
>> *ttm_pool_pre_populated(struct kunit *test,
>> struct ttm_test_devices *devs = priv->devs;
>> struct ttm_pool *pool;
>> struct ttm_tt *tt;
>> - unsigned long order = __fls(size / PAGE_SIZE);
>> int err;
>> - tt = ttm_tt_kunit_init(test, order, caching, size);
>> + tt = ttm_tt_kunit_init(test, 0, caching, size);
>> KUNIT_ASSERT_NOT_NULL(test, tt);
>> pool = kunit_kzalloc(test, sizeof(*pool), GFP_KERNEL);
>
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2024-01-15 11:56 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-01-11 10:28 [PATCH RESEND v9 0/8] Improve test coverage of TTM Karolina Stolarek
2024-01-11 10:28 ` [PATCH RESEND v9 1/8] drm/ttm/tests: Fix argument in ttm_tt_kunit_init() Karolina Stolarek
2024-01-11 14:59 ` Christian König
2024-01-11 15:54 ` Karolina Stolarek
2024-01-15 11:56 ` Somalapuram, Amaranath
2024-01-11 10:28 ` [PATCH RESEND v9 2/8] drm/ttm/tests: Use an init function from the helpers lib Karolina Stolarek
2024-01-11 10:28 ` [PATCH RESEND v9 3/8] drm/ttm/tests: Test simple BO creation and validation Karolina Stolarek
2024-01-11 10:28 ` [PATCH RESEND v9 4/8] drm/ttm/tests: Add tests with mock resource managers Karolina Stolarek
2024-01-11 10:28 ` [PATCH RESEND v9 5/8] drm/ttm/tests: Add test cases dependent on fence signaling Karolina Stolarek
2024-01-11 10:28 ` [PATCH RESEND v9 6/8] drm/ttm/tests: Add eviction testing Karolina Stolarek
2024-01-11 10:28 ` [PATCH RESEND v9 7/8] drm/ttm/tests: Add tests for ttm_tt_populate Karolina Stolarek
2024-01-11 10:28 ` [PATCH RESEND v9 8/8] drm/ttm/tests: Add TODO file Karolina Stolarek
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.