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