xref: /linux/drivers/gpu/drm/xe/tests/xe_rtp_test.c (revision e7d759f31ca295d589f7420719c311870bb3166f)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright © 2023 Intel Corporation
4  */
5 
6 #include <linux/string.h>
7 #include <linux/xarray.h>
8 
9 #include <drm/drm_drv.h>
10 #include <drm/drm_kunit_helpers.h>
11 
12 #include <kunit/test.h>
13 
14 #include "regs/xe_gt_regs.h"
15 #include "regs/xe_reg_defs.h"
16 #include "xe_device.h"
17 #include "xe_device_types.h"
18 #include "xe_pci_test.h"
19 #include "xe_reg_sr.h"
20 #include "xe_rtp.h"
21 
22 #define REGULAR_REG1	XE_REG(1)
23 #define REGULAR_REG2	XE_REG(2)
24 #define REGULAR_REG3	XE_REG(3)
25 #define MCR_REG1	XE_REG_MCR(1)
26 #define MCR_REG2	XE_REG_MCR(2)
27 #define MCR_REG3	XE_REG_MCR(3)
28 #define MASKED_REG1	XE_REG(1, XE_REG_OPTION_MASKED)
29 
30 #undef XE_REG_MCR
31 #define XE_REG_MCR(...)     XE_REG(__VA_ARGS__, .mcr = 1)
32 
33 struct rtp_test_case {
34 	const char *name;
35 	struct xe_reg expected_reg;
36 	u32 expected_set_bits;
37 	u32 expected_clr_bits;
38 	unsigned long expected_count;
39 	unsigned int expected_sr_errors;
40 	const struct xe_rtp_entry_sr *entries;
41 };
42 
43 static bool match_yes(const struct xe_gt *gt, const struct xe_hw_engine *hwe)
44 {
45 	return true;
46 }
47 
48 static bool match_no(const struct xe_gt *gt, const struct xe_hw_engine *hwe)
49 {
50 	return false;
51 }
52 
53 static const struct rtp_test_case cases[] = {
54 	{
55 		.name = "coalesce-same-reg",
56 		.expected_reg = REGULAR_REG1,
57 		.expected_set_bits = REG_BIT(0) | REG_BIT(1),
58 		.expected_clr_bits = REG_BIT(0) | REG_BIT(1),
59 		.expected_count = 1,
60 		/* Different bits on the same register: create a single entry */
61 		.entries = (const struct xe_rtp_entry_sr[]) {
62 			{ XE_RTP_NAME("basic-1"),
63 			  XE_RTP_RULES(FUNC(match_yes)),
64 			  XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
65 			},
66 			{ XE_RTP_NAME("basic-2"),
67 			  XE_RTP_RULES(FUNC(match_yes)),
68 			  XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(1)))
69 			},
70 			{}
71 		},
72 	},
73 	{
74 		.name = "no-match-no-add",
75 		.expected_reg = REGULAR_REG1,
76 		.expected_set_bits = REG_BIT(0),
77 		.expected_clr_bits = REG_BIT(0),
78 		.expected_count = 1,
79 		/* Don't coalesce second entry since rules don't match */
80 		.entries = (const struct xe_rtp_entry_sr[]) {
81 			{ XE_RTP_NAME("basic-1"),
82 			  XE_RTP_RULES(FUNC(match_yes)),
83 			  XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
84 			},
85 			{ XE_RTP_NAME("basic-2"),
86 			  XE_RTP_RULES(FUNC(match_no)),
87 			  XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(1)))
88 			},
89 			{}
90 		},
91 	},
92 	{
93 		.name = "no-match-no-add-multiple-rules",
94 		.expected_reg = REGULAR_REG1,
95 		.expected_set_bits = REG_BIT(0),
96 		.expected_clr_bits = REG_BIT(0),
97 		.expected_count = 1,
98 		/* Don't coalesce second entry due to one of the rules */
99 		.entries = (const struct xe_rtp_entry_sr[]) {
100 			{ XE_RTP_NAME("basic-1"),
101 			  XE_RTP_RULES(FUNC(match_yes)),
102 			  XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
103 			},
104 			{ XE_RTP_NAME("basic-2"),
105 			  XE_RTP_RULES(FUNC(match_yes), FUNC(match_no)),
106 			  XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(1)))
107 			},
108 			{}
109 		},
110 	},
111 	{
112 		.name = "two-regs-two-entries",
113 		.expected_reg = REGULAR_REG1,
114 		.expected_set_bits = REG_BIT(0),
115 		.expected_clr_bits = REG_BIT(0),
116 		.expected_count = 2,
117 		/* Same bits on different registers are not coalesced */
118 		.entries = (const struct xe_rtp_entry_sr[]) {
119 			{ XE_RTP_NAME("basic-1"),
120 			  XE_RTP_RULES(FUNC(match_yes)),
121 			  XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
122 			},
123 			{ XE_RTP_NAME("basic-2"),
124 			  XE_RTP_RULES(FUNC(match_yes)),
125 			  XE_RTP_ACTIONS(SET(REGULAR_REG2, REG_BIT(0)))
126 			},
127 			{}
128 		},
129 	},
130 	{
131 		.name = "clr-one-set-other",
132 		.expected_reg = REGULAR_REG1,
133 		.expected_set_bits = REG_BIT(0),
134 		.expected_clr_bits = REG_BIT(1) | REG_BIT(0),
135 		.expected_count = 1,
136 		/* Check clr vs set actions on different bits */
137 		.entries = (const struct xe_rtp_entry_sr[]) {
138 			{ XE_RTP_NAME("basic-1"),
139 			  XE_RTP_RULES(FUNC(match_yes)),
140 			  XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
141 			},
142 			{ XE_RTP_NAME("basic-2"),
143 			  XE_RTP_RULES(FUNC(match_yes)),
144 			  XE_RTP_ACTIONS(CLR(REGULAR_REG1, REG_BIT(1)))
145 			},
146 			{}
147 		},
148 	},
149 	{
150 #define TEMP_MASK	REG_GENMASK(10, 8)
151 #define TEMP_FIELD	REG_FIELD_PREP(TEMP_MASK, 2)
152 		.name = "set-field",
153 		.expected_reg = REGULAR_REG1,
154 		.expected_set_bits = TEMP_FIELD,
155 		.expected_clr_bits = TEMP_MASK,
156 		.expected_count = 1,
157 		/* Check FIELD_SET works */
158 		.entries = (const struct xe_rtp_entry_sr[]) {
159 			{ XE_RTP_NAME("basic-1"),
160 			  XE_RTP_RULES(FUNC(match_yes)),
161 			  XE_RTP_ACTIONS(FIELD_SET(REGULAR_REG1,
162 						   TEMP_MASK, TEMP_FIELD))
163 			},
164 			{}
165 		},
166 #undef TEMP_MASK
167 #undef TEMP_FIELD
168 	},
169 	{
170 		.name = "conflict-duplicate",
171 		.expected_reg = REGULAR_REG1,
172 		.expected_set_bits = REG_BIT(0),
173 		.expected_clr_bits = REG_BIT(0),
174 		.expected_count = 1,
175 		.expected_sr_errors = 1,
176 		.entries = (const struct xe_rtp_entry_sr[]) {
177 			{ XE_RTP_NAME("basic-1"),
178 			  XE_RTP_RULES(FUNC(match_yes)),
179 			  XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
180 			},
181 			/* drop: setting same values twice */
182 			{ XE_RTP_NAME("basic-2"),
183 			  XE_RTP_RULES(FUNC(match_yes)),
184 			  XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
185 			},
186 			{}
187 		},
188 	},
189 	{
190 		.name = "conflict-not-disjoint",
191 		.expected_reg = REGULAR_REG1,
192 		.expected_set_bits = REG_BIT(0),
193 		.expected_clr_bits = REG_BIT(0),
194 		.expected_count = 1,
195 		.expected_sr_errors = 1,
196 		.entries = (const struct xe_rtp_entry_sr[]) {
197 			{ XE_RTP_NAME("basic-1"),
198 			  XE_RTP_RULES(FUNC(match_yes)),
199 			  XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
200 			},
201 			/* drop: bits are not disjoint with previous entries */
202 			{ XE_RTP_NAME("basic-2"),
203 			  XE_RTP_RULES(FUNC(match_yes)),
204 			  XE_RTP_ACTIONS(CLR(REGULAR_REG1, REG_GENMASK(1, 0)))
205 			},
206 			{}
207 		},
208 	},
209 	{
210 		.name = "conflict-reg-type",
211 		.expected_reg = REGULAR_REG1,
212 		.expected_set_bits = REG_BIT(0),
213 		.expected_clr_bits = REG_BIT(0),
214 		.expected_count = 1,
215 		.expected_sr_errors = 2,
216 		.entries = (const struct xe_rtp_entry_sr[]) {
217 			{ XE_RTP_NAME("basic-1"),
218 			  XE_RTP_RULES(FUNC(match_yes)),
219 			  XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
220 			},
221 			/* drop: regular vs MCR */
222 			{ XE_RTP_NAME("basic-2"),
223 			  XE_RTP_RULES(FUNC(match_yes)),
224 			  XE_RTP_ACTIONS(SET(MCR_REG1, REG_BIT(1)))
225 			},
226 			/* drop: regular vs masked */
227 			{ XE_RTP_NAME("basic-3"),
228 			  XE_RTP_RULES(FUNC(match_yes)),
229 			  XE_RTP_ACTIONS(SET(MASKED_REG1, REG_BIT(0)))
230 			},
231 			{}
232 		},
233 	},
234 };
235 
236 static void xe_rtp_process_tests(struct kunit *test)
237 {
238 	const struct rtp_test_case *param = test->param_value;
239 	struct xe_device *xe = test->priv;
240 	struct xe_gt *gt = xe_device_get_root_tile(xe)->primary_gt;
241 	struct xe_reg_sr *reg_sr = &gt->reg_sr;
242 	const struct xe_reg_sr_entry *sre, *sr_entry = NULL;
243 	struct xe_rtp_process_ctx ctx = XE_RTP_PROCESS_CTX_INITIALIZER(gt);
244 	unsigned long idx, count = 0;
245 
246 	xe_reg_sr_init(reg_sr, "xe_rtp_tests", xe);
247 	xe_rtp_process_to_sr(&ctx, param->entries, reg_sr);
248 
249 	xa_for_each(&reg_sr->xa, idx, sre) {
250 		if (idx == param->expected_reg.addr)
251 			sr_entry = sre;
252 
253 		count++;
254 	}
255 
256 	KUNIT_EXPECT_EQ(test, count, param->expected_count);
257 	KUNIT_EXPECT_EQ(test, sr_entry->clr_bits, param->expected_clr_bits);
258 	KUNIT_EXPECT_EQ(test, sr_entry->set_bits, param->expected_set_bits);
259 	KUNIT_EXPECT_EQ(test, sr_entry->reg.raw, param->expected_reg.raw);
260 	KUNIT_EXPECT_EQ(test, reg_sr->errors, param->expected_sr_errors);
261 }
262 
263 static void rtp_desc(const struct rtp_test_case *t, char *desc)
264 {
265 	strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE);
266 }
267 
268 KUNIT_ARRAY_PARAM(rtp, cases, rtp_desc);
269 
270 static int xe_rtp_test_init(struct kunit *test)
271 {
272 	struct xe_device *xe;
273 	struct device *dev;
274 	int ret;
275 
276 	dev = drm_kunit_helper_alloc_device(test);
277 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
278 
279 	xe = drm_kunit_helper_alloc_drm_device(test, dev,
280 					       struct xe_device,
281 					       drm, DRIVER_GEM);
282 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xe);
283 
284 	/* Initialize an empty device */
285 	test->priv = NULL;
286 	ret = xe_pci_fake_device_init(xe);
287 	KUNIT_ASSERT_EQ(test, ret, 0);
288 
289 	xe->drm.dev = dev;
290 	test->priv = xe;
291 
292 	return 0;
293 }
294 
295 static void xe_rtp_test_exit(struct kunit *test)
296 {
297 	struct xe_device *xe = test->priv;
298 
299 	drm_kunit_helper_free_device(test, xe->drm.dev);
300 }
301 
302 static struct kunit_case xe_rtp_tests[] = {
303 	KUNIT_CASE_PARAM(xe_rtp_process_tests, rtp_gen_params),
304 	{}
305 };
306 
307 static struct kunit_suite xe_rtp_test_suite = {
308 	.name = "xe_rtp",
309 	.init = xe_rtp_test_init,
310 	.exit = xe_rtp_test_exit,
311 	.test_cases = xe_rtp_tests,
312 };
313 
314 kunit_test_suite(xe_rtp_test_suite);
315 
316 MODULE_AUTHOR("Intel Corporation");
317 MODULE_LICENSE("GPL");
318 MODULE_DESCRIPTION("xe_rtp kunit test");
319 MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING);
320