1 // SPDX-License-Identifier: GPL-2.0 AND MIT
2 /*
3  * Copyright © 2023 Intel Corporation
4  */
5 
6 #include <kunit/test.h>
7 
8 #include "xe_device.h"
9 #include "xe_kunit_helpers.h"
10 
guc_dbm_test_init(struct kunit * test)11 static int guc_dbm_test_init(struct kunit *test)
12 {
13 	struct xe_guc_db_mgr *dbm;
14 
15 	xe_kunit_helper_xe_device_test_init(test);
16 	dbm = &xe_device_get_gt(test->priv, 0)->uc.guc.dbm;
17 
18 	mutex_init(dbm_mutex(dbm));
19 	test->priv = dbm;
20 	return 0;
21 }
22 
test_empty(struct kunit * test)23 static void test_empty(struct kunit *test)
24 {
25 	struct xe_guc_db_mgr *dbm = test->priv;
26 
27 	KUNIT_ASSERT_EQ(test, xe_guc_db_mgr_init(dbm, 0), 0);
28 	KUNIT_ASSERT_EQ(test, dbm->count, 0);
29 
30 	mutex_lock(dbm_mutex(dbm));
31 	KUNIT_EXPECT_LT(test, xe_guc_db_mgr_reserve_id_locked(dbm), 0);
32 	mutex_unlock(dbm_mutex(dbm));
33 
34 	KUNIT_EXPECT_LT(test, xe_guc_db_mgr_reserve_range(dbm, 1, 0), 0);
35 }
36 
test_default(struct kunit * test)37 static void test_default(struct kunit *test)
38 {
39 	struct xe_guc_db_mgr *dbm = test->priv;
40 
41 	KUNIT_ASSERT_EQ(test, xe_guc_db_mgr_init(dbm, ~0), 0);
42 	KUNIT_ASSERT_EQ(test, dbm->count, GUC_NUM_DOORBELLS);
43 }
44 
45 static const unsigned int guc_dbm_params[] = {
46 	GUC_NUM_DOORBELLS / 64,
47 	GUC_NUM_DOORBELLS / 32,
48 	GUC_NUM_DOORBELLS / 8,
49 	GUC_NUM_DOORBELLS,
50 };
51 
uint_param_get_desc(const unsigned int * p,char * desc)52 static void uint_param_get_desc(const unsigned int *p, char *desc)
53 {
54 	snprintf(desc, KUNIT_PARAM_DESC_SIZE, "%u", *p);
55 }
56 
57 KUNIT_ARRAY_PARAM(guc_dbm, guc_dbm_params, uint_param_get_desc);
58 
test_size(struct kunit * test)59 static void test_size(struct kunit *test)
60 {
61 	const unsigned int *p = test->param_value;
62 	struct xe_guc_db_mgr *dbm = test->priv;
63 	unsigned int n;
64 	int id;
65 
66 	KUNIT_ASSERT_EQ(test, xe_guc_db_mgr_init(dbm, *p), 0);
67 	KUNIT_ASSERT_EQ(test, dbm->count, *p);
68 
69 	mutex_lock(dbm_mutex(dbm));
70 	for (n = 0; n < *p; n++) {
71 		KUNIT_EXPECT_GE(test, id = xe_guc_db_mgr_reserve_id_locked(dbm), 0);
72 		KUNIT_EXPECT_LT(test, id, dbm->count);
73 	}
74 	KUNIT_EXPECT_LT(test, xe_guc_db_mgr_reserve_id_locked(dbm), 0);
75 	mutex_unlock(dbm_mutex(dbm));
76 
77 	mutex_lock(dbm_mutex(dbm));
78 	for (n = 0; n < *p; n++)
79 		xe_guc_db_mgr_release_id_locked(dbm, n);
80 	mutex_unlock(dbm_mutex(dbm));
81 }
82 
test_reuse(struct kunit * test)83 static void test_reuse(struct kunit *test)
84 {
85 	const unsigned int *p = test->param_value;
86 	struct xe_guc_db_mgr *dbm = test->priv;
87 	unsigned int n;
88 
89 	KUNIT_ASSERT_EQ(test, xe_guc_db_mgr_init(dbm, *p), 0);
90 
91 	mutex_lock(dbm_mutex(dbm));
92 	for (n = 0; n < *p; n++)
93 		KUNIT_EXPECT_GE(test, xe_guc_db_mgr_reserve_id_locked(dbm), 0);
94 	KUNIT_EXPECT_LT(test, xe_guc_db_mgr_reserve_id_locked(dbm), 0);
95 	mutex_unlock(dbm_mutex(dbm));
96 
97 	mutex_lock(dbm_mutex(dbm));
98 	for (n = 0; n < *p; n++) {
99 		xe_guc_db_mgr_release_id_locked(dbm, n);
100 		KUNIT_EXPECT_EQ(test, xe_guc_db_mgr_reserve_id_locked(dbm), n);
101 	}
102 	KUNIT_EXPECT_LT(test, xe_guc_db_mgr_reserve_id_locked(dbm), 0);
103 	mutex_unlock(dbm_mutex(dbm));
104 
105 	mutex_lock(dbm_mutex(dbm));
106 	for (n = 0; n < *p; n++)
107 		xe_guc_db_mgr_release_id_locked(dbm, n);
108 	mutex_unlock(dbm_mutex(dbm));
109 }
110 
test_range_overlap(struct kunit * test)111 static void test_range_overlap(struct kunit *test)
112 {
113 	const unsigned int *p = test->param_value;
114 	struct xe_guc_db_mgr *dbm = test->priv;
115 	int id1, id2, id3;
116 	unsigned int n;
117 
118 	KUNIT_ASSERT_EQ(test, xe_guc_db_mgr_init(dbm, ~0), 0);
119 	KUNIT_ASSERT_LE(test, *p, dbm->count);
120 
121 	KUNIT_ASSERT_GE(test, id1 = xe_guc_db_mgr_reserve_range(dbm, *p, 0), 0);
122 	for (n = 0; n < dbm->count - *p; n++) {
123 		KUNIT_ASSERT_GE(test, id2 = xe_guc_db_mgr_reserve_range(dbm, 1, 0), 0);
124 		KUNIT_ASSERT_NE(test, id2, id1);
125 		KUNIT_ASSERT_NE_MSG(test, id2 < id1, id2 > id1 + *p - 1,
126 				    "id1=%d id2=%d", id1, id2);
127 	}
128 	KUNIT_ASSERT_LT(test, xe_guc_db_mgr_reserve_range(dbm, 1, 0), 0);
129 	xe_guc_db_mgr_release_range(dbm, 0, dbm->count);
130 
131 	if (*p >= 1) {
132 		KUNIT_ASSERT_GE(test, id1 = xe_guc_db_mgr_reserve_range(dbm, 1, 0), 0);
133 		KUNIT_ASSERT_GE(test, id2 = xe_guc_db_mgr_reserve_range(dbm, *p - 1, 0), 0);
134 		KUNIT_ASSERT_NE(test, id2, id1);
135 		KUNIT_ASSERT_NE_MSG(test, id1 < id2, id1 > id2 + *p - 2,
136 				    "id1=%d id2=%d", id1, id2);
137 		for (n = 0; n < dbm->count - *p; n++) {
138 			KUNIT_ASSERT_GE(test, id3 = xe_guc_db_mgr_reserve_range(dbm, 1, 0), 0);
139 			KUNIT_ASSERT_NE(test, id3, id1);
140 			KUNIT_ASSERT_NE(test, id3, id2);
141 			KUNIT_ASSERT_NE_MSG(test, id3 < id2, id3 > id2 + *p - 2,
142 					    "id3=%d id2=%d", id3, id2);
143 		}
144 		KUNIT_ASSERT_LT(test, xe_guc_db_mgr_reserve_range(dbm, 1, 0), 0);
145 		xe_guc_db_mgr_release_range(dbm, 0, dbm->count);
146 	}
147 }
148 
test_range_compact(struct kunit * test)149 static void test_range_compact(struct kunit *test)
150 {
151 	const unsigned int *p = test->param_value;
152 	struct xe_guc_db_mgr *dbm = test->priv;
153 	unsigned int n;
154 
155 	KUNIT_ASSERT_EQ(test, xe_guc_db_mgr_init(dbm, ~0), 0);
156 	KUNIT_ASSERT_NE(test, *p, 0);
157 	KUNIT_ASSERT_LE(test, *p, dbm->count);
158 	if (dbm->count % *p)
159 		kunit_skip(test, "must be divisible");
160 
161 	KUNIT_ASSERT_GE(test, xe_guc_db_mgr_reserve_range(dbm, *p, 0), 0);
162 	for (n = 1; n < dbm->count / *p; n++)
163 		KUNIT_ASSERT_GE(test, xe_guc_db_mgr_reserve_range(dbm, *p, 0), 0);
164 	KUNIT_ASSERT_LT(test, xe_guc_db_mgr_reserve_range(dbm, 1, 0), 0);
165 	xe_guc_db_mgr_release_range(dbm, 0, dbm->count);
166 }
167 
test_range_spare(struct kunit * test)168 static void test_range_spare(struct kunit *test)
169 {
170 	const unsigned int *p = test->param_value;
171 	struct xe_guc_db_mgr *dbm = test->priv;
172 	int id;
173 
174 	KUNIT_ASSERT_EQ(test, xe_guc_db_mgr_init(dbm, ~0), 0);
175 	KUNIT_ASSERT_LE(test, *p, dbm->count);
176 
177 	KUNIT_ASSERT_LT(test, xe_guc_db_mgr_reserve_range(dbm, *p, dbm->count), 0);
178 	KUNIT_ASSERT_LT(test, xe_guc_db_mgr_reserve_range(dbm, *p, dbm->count - *p + 1), 0);
179 	KUNIT_ASSERT_EQ(test, id = xe_guc_db_mgr_reserve_range(dbm, *p, dbm->count - *p), 0);
180 	KUNIT_ASSERT_LT(test, xe_guc_db_mgr_reserve_range(dbm, 1, dbm->count - *p), 0);
181 	xe_guc_db_mgr_release_range(dbm, id, *p);
182 }
183 
184 static struct kunit_case guc_dbm_test_cases[] = {
185 	KUNIT_CASE(test_empty),
186 	KUNIT_CASE(test_default),
187 	KUNIT_CASE_PARAM(test_size, guc_dbm_gen_params),
188 	KUNIT_CASE_PARAM(test_reuse, guc_dbm_gen_params),
189 	KUNIT_CASE_PARAM(test_range_overlap, guc_dbm_gen_params),
190 	KUNIT_CASE_PARAM(test_range_compact, guc_dbm_gen_params),
191 	KUNIT_CASE_PARAM(test_range_spare, guc_dbm_gen_params),
192 	{}
193 };
194 
195 static struct kunit_suite guc_dbm_suite = {
196 	.name = "guc_dbm",
197 	.test_cases = guc_dbm_test_cases,
198 	.init = guc_dbm_test_init,
199 };
200 
201 kunit_test_suites(&guc_dbm_suite);
202