19710631cSChristian König // SPDX-License-Identifier: MIT
29710631cSChristian König /*
39710631cSChristian König  * Copyright 2022 Advanced Micro Devices, Inc.
49710631cSChristian König  */
59710631cSChristian König 
69710631cSChristian König #define pr_fmt(fmt) "drm_exec: " fmt
79710631cSChristian König 
89710631cSChristian König #include <kunit/test.h>
99710631cSChristian König 
109710631cSChristian König #include <linux/module.h>
119710631cSChristian König #include <linux/prime_numbers.h>
129710631cSChristian König 
139710631cSChristian König #include <drm/drm_exec.h>
149710631cSChristian König #include <drm/drm_device.h>
150f249678SArthur Grillo #include <drm/drm_drv.h>
169710631cSChristian König #include <drm/drm_gem.h>
170f249678SArthur Grillo #include <drm/drm_kunit_helpers.h>
189710631cSChristian König 
199710631cSChristian König #include "../lib/drm_random.h"
209710631cSChristian König 
210f249678SArthur Grillo struct drm_exec_priv {
220f249678SArthur Grillo 	struct device *dev;
230f249678SArthur Grillo 	struct drm_device *drm;
240f249678SArthur Grillo };
250f249678SArthur Grillo 
drm_exec_test_init(struct kunit * test)260f249678SArthur Grillo static int drm_exec_test_init(struct kunit *test)
270f249678SArthur Grillo {
280f249678SArthur Grillo 	struct drm_exec_priv *priv;
290f249678SArthur Grillo 
300f249678SArthur Grillo 	priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
310f249678SArthur Grillo 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv);
320f249678SArthur Grillo 
330f249678SArthur Grillo 	test->priv = priv;
340f249678SArthur Grillo 
350f249678SArthur Grillo 	priv->dev = drm_kunit_helper_alloc_device(test);
360f249678SArthur Grillo 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->dev);
370f249678SArthur Grillo 
380f249678SArthur Grillo 	priv->drm = __drm_kunit_helper_alloc_drm_device(test, priv->dev, sizeof(*priv->drm), 0,
390f249678SArthur Grillo 							DRIVER_MODESET);
400f249678SArthur Grillo 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->drm);
410f249678SArthur Grillo 
420f249678SArthur Grillo 	return 0;
430f249678SArthur Grillo }
449710631cSChristian König 
sanitycheck(struct kunit * test)459710631cSChristian König static void sanitycheck(struct kunit *test)
469710631cSChristian König {
479710631cSChristian König 	struct drm_exec exec;
489710631cSChristian König 
499710631cSChristian König 	drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT);
509710631cSChristian König 	drm_exec_fini(&exec);
519710631cSChristian König 	KUNIT_SUCCEED(test);
529710631cSChristian König }
539710631cSChristian König 
test_lock(struct kunit * test)549710631cSChristian König static void test_lock(struct kunit *test)
559710631cSChristian König {
560f249678SArthur Grillo 	struct drm_exec_priv *priv = test->priv;
579710631cSChristian König 	struct drm_gem_object gobj = { };
589710631cSChristian König 	struct drm_exec exec;
599710631cSChristian König 	int ret;
609710631cSChristian König 
610f249678SArthur Grillo 	drm_gem_private_object_init(priv->drm, &gobj, PAGE_SIZE);
629710631cSChristian König 
639710631cSChristian König 	drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT);
649710631cSChristian König 	drm_exec_until_all_locked(&exec) {
659710631cSChristian König 		ret = drm_exec_lock_obj(&exec, &gobj);
669710631cSChristian König 		drm_exec_retry_on_contention(&exec);
679710631cSChristian König 		KUNIT_EXPECT_EQ(test, ret, 0);
689710631cSChristian König 		if (ret)
699710631cSChristian König 			break;
709710631cSChristian König 	}
719710631cSChristian König 	drm_exec_fini(&exec);
729710631cSChristian König }
739710631cSChristian König 
test_lock_unlock(struct kunit * test)749710631cSChristian König static void test_lock_unlock(struct kunit *test)
759710631cSChristian König {
760f249678SArthur Grillo 	struct drm_exec_priv *priv = test->priv;
779710631cSChristian König 	struct drm_gem_object gobj = { };
789710631cSChristian König 	struct drm_exec exec;
799710631cSChristian König 	int ret;
809710631cSChristian König 
810f249678SArthur Grillo 	drm_gem_private_object_init(priv->drm, &gobj, PAGE_SIZE);
829710631cSChristian König 
839710631cSChristian König 	drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT);
849710631cSChristian König 	drm_exec_until_all_locked(&exec) {
859710631cSChristian König 		ret = drm_exec_lock_obj(&exec, &gobj);
869710631cSChristian König 		drm_exec_retry_on_contention(&exec);
879710631cSChristian König 		KUNIT_EXPECT_EQ(test, ret, 0);
889710631cSChristian König 		if (ret)
899710631cSChristian König 			break;
909710631cSChristian König 
919710631cSChristian König 		drm_exec_unlock_obj(&exec, &gobj);
929710631cSChristian König 		ret = drm_exec_lock_obj(&exec, &gobj);
939710631cSChristian König 		drm_exec_retry_on_contention(&exec);
949710631cSChristian König 		KUNIT_EXPECT_EQ(test, ret, 0);
959710631cSChristian König 		if (ret)
969710631cSChristian König 			break;
979710631cSChristian König 	}
989710631cSChristian König 	drm_exec_fini(&exec);
999710631cSChristian König }
1009710631cSChristian König 
test_duplicates(struct kunit * test)1019710631cSChristian König static void test_duplicates(struct kunit *test)
1029710631cSChristian König {
1030f249678SArthur Grillo 	struct drm_exec_priv *priv = test->priv;
1049710631cSChristian König 	struct drm_gem_object gobj = { };
1059710631cSChristian König 	struct drm_exec exec;
1069710631cSChristian König 	int ret;
1079710631cSChristian König 
1080f249678SArthur Grillo 	drm_gem_private_object_init(priv->drm, &gobj, PAGE_SIZE);
1099710631cSChristian König 
1109710631cSChristian König 	drm_exec_init(&exec, DRM_EXEC_IGNORE_DUPLICATES);
1119710631cSChristian König 	drm_exec_until_all_locked(&exec) {
1129710631cSChristian König 		ret = drm_exec_lock_obj(&exec, &gobj);
1139710631cSChristian König 		drm_exec_retry_on_contention(&exec);
1149710631cSChristian König 		KUNIT_EXPECT_EQ(test, ret, 0);
1159710631cSChristian König 		if (ret)
1169710631cSChristian König 			break;
1179710631cSChristian König 
1189710631cSChristian König 		ret = drm_exec_lock_obj(&exec, &gobj);
1199710631cSChristian König 		drm_exec_retry_on_contention(&exec);
1209710631cSChristian König 		KUNIT_EXPECT_EQ(test, ret, 0);
1219710631cSChristian König 		if (ret)
1229710631cSChristian König 			break;
1239710631cSChristian König 	}
1249710631cSChristian König 	drm_exec_unlock_obj(&exec, &gobj);
1259710631cSChristian König 	drm_exec_fini(&exec);
1269710631cSChristian König }
1279710631cSChristian König 
test_prepare(struct kunit * test)1289710631cSChristian König static void test_prepare(struct kunit *test)
1299710631cSChristian König {
1300f249678SArthur Grillo 	struct drm_exec_priv *priv = test->priv;
1319710631cSChristian König 	struct drm_gem_object gobj = { };
1329710631cSChristian König 	struct drm_exec exec;
1339710631cSChristian König 	int ret;
1349710631cSChristian König 
1350f249678SArthur Grillo 	drm_gem_private_object_init(priv->drm, &gobj, PAGE_SIZE);
1369710631cSChristian König 
1379710631cSChristian König 	drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT);
1389710631cSChristian König 	drm_exec_until_all_locked(&exec) {
1399710631cSChristian König 		ret = drm_exec_prepare_obj(&exec, &gobj, 1);
1409710631cSChristian König 		drm_exec_retry_on_contention(&exec);
1419710631cSChristian König 		KUNIT_EXPECT_EQ(test, ret, 0);
1429710631cSChristian König 		if (ret)
1439710631cSChristian König 			break;
1449710631cSChristian König 	}
1459710631cSChristian König 	drm_exec_fini(&exec);
146*806fd6d0SDanilo Krummrich 
147*806fd6d0SDanilo Krummrich 	drm_gem_private_object_fini(&gobj);
1489710631cSChristian König }
1499710631cSChristian König 
test_prepare_array(struct kunit * test)1509710631cSChristian König static void test_prepare_array(struct kunit *test)
1519710631cSChristian König {
1520f249678SArthur Grillo 	struct drm_exec_priv *priv = test->priv;
1539710631cSChristian König 	struct drm_gem_object gobj1 = { };
1549710631cSChristian König 	struct drm_gem_object gobj2 = { };
1559710631cSChristian König 	struct drm_gem_object *array[] = { &gobj1, &gobj2 };
1569710631cSChristian König 	struct drm_exec exec;
1579710631cSChristian König 	int ret;
1589710631cSChristian König 
1590f249678SArthur Grillo 	drm_gem_private_object_init(priv->drm, &gobj1, PAGE_SIZE);
1600f249678SArthur Grillo 	drm_gem_private_object_init(priv->drm, &gobj2, PAGE_SIZE);
1619710631cSChristian König 
1629710631cSChristian König 	drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT);
1639710631cSChristian König 	drm_exec_until_all_locked(&exec)
1649710631cSChristian König 		ret = drm_exec_prepare_array(&exec, array, ARRAY_SIZE(array),
1659710631cSChristian König 					     1);
1669710631cSChristian König 	KUNIT_EXPECT_EQ(test, ret, 0);
1679710631cSChristian König 	drm_exec_fini(&exec);
168*806fd6d0SDanilo Krummrich 
169*806fd6d0SDanilo Krummrich 	drm_gem_private_object_fini(&gobj1);
170*806fd6d0SDanilo Krummrich 	drm_gem_private_object_fini(&gobj2);
1719710631cSChristian König }
1729710631cSChristian König 
test_multiple_loops(struct kunit * test)173991eb531SChristian König static void test_multiple_loops(struct kunit *test)
174991eb531SChristian König {
175991eb531SChristian König 	struct drm_exec exec;
176991eb531SChristian König 
177991eb531SChristian König 	drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT);
178991eb531SChristian König 	drm_exec_until_all_locked(&exec)
179991eb531SChristian König 	{
180991eb531SChristian König 		break;
181991eb531SChristian König 	}
182991eb531SChristian König 	drm_exec_fini(&exec);
183991eb531SChristian König 
184991eb531SChristian König 	drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT);
185991eb531SChristian König 	drm_exec_until_all_locked(&exec)
186991eb531SChristian König 	{
187991eb531SChristian König 		break;
188991eb531SChristian König 	}
189991eb531SChristian König 	drm_exec_fini(&exec);
190991eb531SChristian König 	KUNIT_SUCCEED(test);
191991eb531SChristian König }
192991eb531SChristian König 
1939710631cSChristian König static struct kunit_case drm_exec_tests[] = {
1949710631cSChristian König 	KUNIT_CASE(sanitycheck),
1959710631cSChristian König 	KUNIT_CASE(test_lock),
1969710631cSChristian König 	KUNIT_CASE(test_lock_unlock),
1979710631cSChristian König 	KUNIT_CASE(test_duplicates),
1989710631cSChristian König 	KUNIT_CASE(test_prepare),
1999710631cSChristian König 	KUNIT_CASE(test_prepare_array),
200991eb531SChristian König 	KUNIT_CASE(test_multiple_loops),
2019710631cSChristian König 	{}
2029710631cSChristian König };
2039710631cSChristian König 
2049710631cSChristian König static struct kunit_suite drm_exec_test_suite = {
2059710631cSChristian König 	.name = "drm_exec",
2060f249678SArthur Grillo 	.init = drm_exec_test_init,
2079710631cSChristian König 	.test_cases = drm_exec_tests,
2089710631cSChristian König };
2099710631cSChristian König 
2109710631cSChristian König kunit_test_suite(drm_exec_test_suite);
2119710631cSChristian König 
2129710631cSChristian König MODULE_AUTHOR("AMD");
2139710631cSChristian König MODULE_LICENSE("GPL and additional rights");
214