Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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
34struct 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
44static bool match_yes(const struct xe_gt *gt, const struct xe_hw_engine *hwe)
45{
46 return true;
47}
48
49static bool match_no(const struct xe_gt *gt, const struct xe_hw_engine *hwe)
50{
51 return false;
52}
53
54static 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
237static 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 = >->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(®_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
264static void rtp_desc(const struct rtp_test_case *t, char *desc)
265{
266 strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE);
267}
268
269KUNIT_ARRAY_PARAM(rtp, cases, rtp_desc);
270
271static 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
294static 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
301static struct kunit_case xe_rtp_tests[] = {
302 KUNIT_CASE_PARAM(xe_rtp_process_tests, rtp_gen_params),
303 {}
304};
305
306static 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
313kunit_test_suite(xe_rtp_test_suite);