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
11static 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
23static 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
37static 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
45static 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
52static void uint_param_get_desc(const unsigned int *p, char *desc)
53{
54	snprintf(desc, KUNIT_PARAM_DESC_SIZE, "%u", *p);
55}
56
57KUNIT_ARRAY_PARAM(guc_dbm, guc_dbm_params, uint_param_get_desc);
58
59static 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
83static 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
111static 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
149static 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
168static 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
184static 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
195static 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
201kunit_test_suites(&guc_dbm_suite);
202