1 // SPDX-License-Identifier: GPL-2.0 AND MIT
2 /*
3  * Copyright © 2023 Intel Corporation
4  */
5 
6 #include <kunit/static_stub.h>
7 #include <kunit/test.h>
8 #include <kunit/test-bug.h>
9 
10 #include "xe_device.h"
11 #include "xe_kunit_helpers.h"
12 #include "xe_pci_test.h"
13 
14 #define TEST_RID	1234
15 #define TEST_VFID	5
16 #define TEST_LEN	6
17 #define TEST_ACTION	0xa
18 #define TEST_DATA(n)	(0xd0 + (n))
19 
replacement_relay_get_totalvfs(struct xe_guc_relay * relay)20 static int replacement_relay_get_totalvfs(struct xe_guc_relay *relay)
21 {
22 	return TEST_VFID;
23 }
24 
relay_test_init(struct kunit * test)25 static int relay_test_init(struct kunit *test)
26 {
27 	struct xe_pci_fake_data fake = {
28 		.sriov_mode = XE_SRIOV_MODE_PF,
29 		.platform = XE_TIGERLAKE, /* some random platform */
30 		.subplatform = XE_SUBPLATFORM_NONE,
31 	};
32 	struct xe_guc_relay *relay;
33 	struct xe_device *xe;
34 
35 	test->priv = &fake;
36 	xe_kunit_helper_xe_device_test_init(test);
37 
38 	xe = test->priv;
39 	KUNIT_ASSERT_EQ(test, xe_sriov_init(xe), 0);
40 
41 	relay = &xe_device_get_gt(xe, 0)->uc.guc.relay;
42 	kunit_activate_static_stub(test, relay_get_totalvfs,
43 				   replacement_relay_get_totalvfs);
44 
45 	KUNIT_ASSERT_EQ(test, xe_guc_relay_init(relay), 0);
46 	KUNIT_EXPECT_TRUE(test, relay_is_ready(relay));
47 	relay->last_rid = TEST_RID - 1;
48 
49 	test->priv = relay;
50 	return 0;
51 }
52 
53 static const u32 TEST_MSG[TEST_LEN] = {
54 	FIELD_PREP_CONST(GUC_HXG_MSG_0_ORIGIN, GUC_HXG_ORIGIN_HOST) |
55 	FIELD_PREP_CONST(GUC_HXG_MSG_0_TYPE, GUC_HXG_TYPE_EVENT) |
56 	FIELD_PREP_CONST(GUC_HXG_EVENT_MSG_0_ACTION, TEST_ACTION) |
57 	FIELD_PREP_CONST(GUC_HXG_EVENT_MSG_0_DATA0, TEST_DATA(0)),
58 	TEST_DATA(1), TEST_DATA(2), TEST_DATA(3), TEST_DATA(4),
59 };
60 
replacement_xe_guc_ct_send_recv_always_fails(struct xe_guc_ct * ct,const u32 * msg,u32 len,u32 * response_buffer)61 static int replacement_xe_guc_ct_send_recv_always_fails(struct xe_guc_ct *ct,
62 							const u32 *msg, u32 len,
63 							u32 *response_buffer)
64 {
65 	struct kunit *test = kunit_get_current_test();
66 
67 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ct);
68 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, msg);
69 	KUNIT_ASSERT_GE(test, len, GUC_HXG_MSG_MIN_LEN);
70 
71 	return -ECOMM;
72 }
73 
replacement_xe_guc_ct_send_recv_expects_pf2guc_relay(struct xe_guc_ct * ct,const u32 * msg,u32 len,u32 * response_buffer)74 static int replacement_xe_guc_ct_send_recv_expects_pf2guc_relay(struct xe_guc_ct *ct,
75 								const u32 *msg, u32 len,
76 								u32 *response_buffer)
77 {
78 	struct kunit *test = kunit_get_current_test();
79 
80 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ct);
81 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, msg);
82 	KUNIT_ASSERT_GE(test, len, PF2GUC_RELAY_TO_VF_REQUEST_MSG_MIN_LEN);
83 	KUNIT_ASSERT_EQ(test, len, PF2GUC_RELAY_TO_VF_REQUEST_MSG_MIN_LEN + TEST_LEN);
84 	KUNIT_EXPECT_EQ(test, GUC_HXG_ORIGIN_HOST, FIELD_GET(GUC_HXG_MSG_0_ORIGIN, msg[0]));
85 	KUNIT_EXPECT_EQ(test, GUC_HXG_TYPE_REQUEST, FIELD_GET(GUC_HXG_MSG_0_TYPE, msg[0]));
86 	KUNIT_EXPECT_EQ(test, XE_GUC_ACTION_PF2GUC_RELAY_TO_VF,
87 			FIELD_GET(GUC_HXG_REQUEST_MSG_0_ACTION, msg[0]));
88 	KUNIT_EXPECT_EQ(test, TEST_VFID,
89 			FIELD_GET(PF2GUC_RELAY_TO_VF_REQUEST_MSG_1_VFID, msg[1]));
90 	KUNIT_EXPECT_EQ(test, TEST_RID,
91 			FIELD_GET(PF2GUC_RELAY_TO_VF_REQUEST_MSG_2_RELAY_ID, msg[2]));
92 	KUNIT_EXPECT_MEMEQ(test, TEST_MSG, msg + PF2GUC_RELAY_TO_VF_REQUEST_MSG_MIN_LEN,
93 			   sizeof(u32) * TEST_LEN);
94 	return 0;
95 }
96 
97 static const u32 test_guc2pf[GUC2PF_RELAY_FROM_VF_EVENT_MSG_MAX_LEN] = {
98 	/* transport */
99 	FIELD_PREP_CONST(GUC_HXG_MSG_0_ORIGIN, GUC_HXG_ORIGIN_GUC) |
100 	FIELD_PREP_CONST(GUC_HXG_MSG_0_TYPE, GUC_HXG_TYPE_EVENT) |
101 	FIELD_PREP_CONST(GUC_HXG_EVENT_MSG_0_ACTION, XE_GUC_ACTION_GUC2PF_RELAY_FROM_VF),
102 	FIELD_PREP_CONST(GUC2PF_RELAY_FROM_VF_EVENT_MSG_1_VFID, TEST_VFID),
103 	FIELD_PREP_CONST(GUC2PF_RELAY_FROM_VF_EVENT_MSG_2_RELAY_ID, TEST_RID),
104 	/* payload */
105 	FIELD_PREP_CONST(GUC_HXG_MSG_0_ORIGIN, GUC_HXG_ORIGIN_HOST) |
106 	FIELD_PREP_CONST(GUC_HXG_MSG_0_TYPE, GUC_HXG_TYPE_RESPONSE_SUCCESS),
107 };
108 
109 static const u32 test_guc2vf[GUC2VF_RELAY_FROM_PF_EVENT_MSG_MAX_LEN] = {
110 	/* transport */
111 	FIELD_PREP_CONST(GUC_HXG_MSG_0_ORIGIN, GUC_HXG_ORIGIN_GUC) |
112 	FIELD_PREP_CONST(GUC_HXG_MSG_0_TYPE, GUC_HXG_TYPE_EVENT) |
113 	FIELD_PREP_CONST(GUC_HXG_EVENT_MSG_0_ACTION, XE_GUC_ACTION_GUC2VF_RELAY_FROM_PF),
114 	FIELD_PREP_CONST(GUC2VF_RELAY_FROM_PF_EVENT_MSG_1_RELAY_ID, TEST_RID),
115 	/* payload */
116 	FIELD_PREP_CONST(GUC_HXG_MSG_0_ORIGIN, GUC_HXG_ORIGIN_HOST) |
117 	FIELD_PREP_CONST(GUC_HXG_MSG_0_TYPE, GUC_HXG_TYPE_RESPONSE_SUCCESS),
118 };
119 
pf_rejects_guc2pf_too_short(struct kunit * test)120 static void pf_rejects_guc2pf_too_short(struct kunit *test)
121 {
122 	const u32 len = GUC2PF_RELAY_FROM_VF_EVENT_MSG_MIN_LEN - 1;
123 	struct xe_guc_relay *relay = test->priv;
124 	const u32 *msg = test_guc2pf;
125 
126 	KUNIT_ASSERT_EQ(test, -EPROTO, xe_guc_relay_process_guc2pf(relay, msg, len));
127 }
128 
pf_rejects_guc2pf_too_long(struct kunit * test)129 static void pf_rejects_guc2pf_too_long(struct kunit *test)
130 {
131 	const u32 len = GUC2PF_RELAY_FROM_VF_EVENT_MSG_MAX_LEN + 1;
132 	struct xe_guc_relay *relay = test->priv;
133 	const u32 *msg = test_guc2pf;
134 
135 	KUNIT_ASSERT_EQ(test, -EMSGSIZE, xe_guc_relay_process_guc2pf(relay, msg, len));
136 }
137 
pf_rejects_guc2pf_no_payload(struct kunit * test)138 static void pf_rejects_guc2pf_no_payload(struct kunit *test)
139 {
140 	const u32 len = GUC2PF_RELAY_FROM_VF_EVENT_MSG_MIN_LEN;
141 	struct xe_guc_relay *relay = test->priv;
142 	const u32 *msg = test_guc2pf;
143 
144 	KUNIT_ASSERT_EQ(test, -EPROTO, xe_guc_relay_process_guc2pf(relay, msg, len));
145 }
146 
pf_fails_no_payload(struct kunit * test)147 static void pf_fails_no_payload(struct kunit *test)
148 {
149 	struct xe_guc_relay *relay = test->priv;
150 	const u32 msg = 0;
151 
152 	KUNIT_ASSERT_EQ(test, -EPROTO, relay_process_msg(relay, TEST_VFID, TEST_RID, &msg, 0));
153 }
154 
pf_fails_bad_origin(struct kunit * test)155 static void pf_fails_bad_origin(struct kunit *test)
156 {
157 	struct xe_guc_relay *relay = test->priv;
158 	static const u32 msg[] = {
159 		FIELD_PREP_CONST(GUC_HXG_MSG_0_ORIGIN, GUC_HXG_ORIGIN_GUC) |
160 		FIELD_PREP_CONST(GUC_HXG_MSG_0_TYPE, GUC_HXG_TYPE_RESPONSE_SUCCESS),
161 	};
162 	u32 len = ARRAY_SIZE(msg);
163 
164 	KUNIT_ASSERT_EQ(test, -EPROTO, relay_process_msg(relay, TEST_VFID, TEST_RID, msg, len));
165 }
166 
pf_fails_bad_type(struct kunit * test)167 static void pf_fails_bad_type(struct kunit *test)
168 {
169 	struct xe_guc_relay *relay = test->priv;
170 	const u32 msg[] = {
171 		FIELD_PREP(GUC_HXG_MSG_0_ORIGIN, GUC_HXG_ORIGIN_HOST) |
172 		FIELD_PREP(GUC_HXG_MSG_0_TYPE, 4), /* only 4 is undefined */
173 	};
174 	u32 len = ARRAY_SIZE(msg);
175 
176 	KUNIT_ASSERT_EQ(test, -EBADRQC, relay_process_msg(relay, TEST_VFID, TEST_RID, msg, len));
177 }
178 
pf_txn_reports_error(struct kunit * test)179 static void pf_txn_reports_error(struct kunit *test)
180 {
181 	struct xe_guc_relay *relay = test->priv;
182 	struct relay_transaction *txn;
183 
184 	txn = __relay_get_transaction(relay, false, TEST_VFID, TEST_RID,
185 				      TEST_MSG, TEST_LEN, NULL, 0);
186 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, txn);
187 
188 	kunit_activate_static_stub(test, xe_guc_ct_send_recv,
189 				   replacement_xe_guc_ct_send_recv_always_fails);
190 	KUNIT_EXPECT_EQ(test, -ECOMM, relay_send_transaction(relay, txn));
191 
192 	relay_release_transaction(relay, txn);
193 }
194 
pf_txn_sends_pf2guc(struct kunit * test)195 static void pf_txn_sends_pf2guc(struct kunit *test)
196 {
197 	struct xe_guc_relay *relay = test->priv;
198 	struct relay_transaction *txn;
199 
200 	txn = __relay_get_transaction(relay, false, TEST_VFID, TEST_RID,
201 				      TEST_MSG, TEST_LEN, NULL, 0);
202 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, txn);
203 
204 	kunit_activate_static_stub(test, xe_guc_ct_send_recv,
205 				   replacement_xe_guc_ct_send_recv_expects_pf2guc_relay);
206 	KUNIT_ASSERT_EQ(test, 0, relay_send_transaction(relay, txn));
207 
208 	relay_release_transaction(relay, txn);
209 }
210 
pf_sends_pf2guc(struct kunit * test)211 static void pf_sends_pf2guc(struct kunit *test)
212 {
213 	struct xe_guc_relay *relay = test->priv;
214 
215 	kunit_activate_static_stub(test, xe_guc_ct_send_recv,
216 				   replacement_xe_guc_ct_send_recv_expects_pf2guc_relay);
217 	KUNIT_ASSERT_EQ(test, 0,
218 			xe_guc_relay_send_to_vf(relay, TEST_VFID,
219 						TEST_MSG, TEST_LEN, NULL, 0));
220 }
221 
replacement_xe_guc_ct_send_recv_loopback_relay(struct xe_guc_ct * ct,const u32 * msg,u32 len,u32 * response_buffer)222 static int replacement_xe_guc_ct_send_recv_loopback_relay(struct xe_guc_ct *ct,
223 							  const u32 *msg, u32 len,
224 							  u32 *response_buffer)
225 {
226 	struct kunit *test = kunit_get_current_test();
227 	struct xe_guc_relay *relay = test->priv;
228 	u32 *reply = kunit_kzalloc(test, len * sizeof(u32), GFP_KERNEL);
229 	int (*guc2relay)(struct xe_guc_relay *, const u32 *, u32);
230 	u32 action;
231 	int err;
232 
233 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ct);
234 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, msg);
235 	KUNIT_ASSERT_GE(test, len, GUC_HXG_MSG_MIN_LEN);
236 	KUNIT_ASSERT_EQ(test, GUC_HXG_TYPE_REQUEST,
237 			FIELD_GET(GUC_HXG_MSG_0_TYPE, msg[0]));
238 	KUNIT_ASSERT_GE(test, len, GUC_HXG_REQUEST_MSG_MIN_LEN);
239 	KUNIT_ASSERT_NOT_NULL(test, reply);
240 
241 	switch (FIELD_GET(GUC_HXG_REQUEST_MSG_0_ACTION, msg[0])) {
242 	case XE_GUC_ACTION_PF2GUC_RELAY_TO_VF:
243 		KUNIT_ASSERT_GE(test, len, PF2GUC_RELAY_TO_VF_REQUEST_MSG_MIN_LEN);
244 		action = XE_GUC_ACTION_GUC2PF_RELAY_FROM_VF;
245 		guc2relay = xe_guc_relay_process_guc2pf;
246 		break;
247 	case XE_GUC_ACTION_VF2GUC_RELAY_TO_PF:
248 		KUNIT_ASSERT_GE(test, len, VF2GUC_RELAY_TO_PF_REQUEST_MSG_MIN_LEN);
249 		action = XE_GUC_ACTION_GUC2VF_RELAY_FROM_PF;
250 		guc2relay = xe_guc_relay_process_guc2vf;
251 		break;
252 	default:
253 		KUNIT_FAIL(test, "bad RELAY action %#x", msg[0]);
254 		return -EINVAL;
255 	}
256 
257 	reply[0] = FIELD_PREP(GUC_HXG_MSG_0_ORIGIN, GUC_HXG_ORIGIN_GUC) |
258 		   FIELD_PREP(GUC_HXG_MSG_0_TYPE, GUC_HXG_TYPE_EVENT) |
259 		   FIELD_PREP(GUC_HXG_EVENT_MSG_0_ACTION, action);
260 	memcpy(reply + 1, msg + 1, sizeof(u32) * (len - 1));
261 
262 	err = guc2relay(relay, reply, len);
263 	KUNIT_EXPECT_EQ(test, err, 0);
264 
265 	return err;
266 }
267 
test_requires_relay_testloop(struct kunit * test)268 static void test_requires_relay_testloop(struct kunit *test)
269 {
270 	/*
271 	 * The debug relay action GUC_RELAY_ACTION_VFXPF_TESTLOOP is available
272 	 * only on builds with CONFIG_DRM_XE_DEBUG_SRIOV enabled.
273 	 * See "kunit.py --kconfig_add" option if it's missing.
274 	 */
275 	if (!IS_ENABLED(CONFIG_DRM_XE_DEBUG_SRIOV))
276 		kunit_skip(test, "requires %s\n", __stringify(CONFIG_DRM_XE_DEBUG_SRIOV));
277 }
278 
pf_loopback_nop(struct kunit * test)279 static void pf_loopback_nop(struct kunit *test)
280 {
281 	struct xe_guc_relay *relay = test->priv;
282 	u32 request[] = {
283 		FIELD_PREP(GUC_HXG_MSG_0_ORIGIN, GUC_HXG_ORIGIN_HOST) |
284 		FIELD_PREP(GUC_HXG_MSG_0_TYPE, GUC_HXG_TYPE_REQUEST) |
285 		FIELD_PREP(GUC_HXG_REQUEST_MSG_0_ACTION, GUC_RELAY_ACTION_VFXPF_TESTLOOP) |
286 		FIELD_PREP(GUC_HXG_REQUEST_MSG_0_DATA0, VFXPF_TESTLOOP_OPCODE_NOP),
287 	};
288 	u32 response[GUC_HXG_RESPONSE_MSG_MIN_LEN];
289 	int ret;
290 
291 	test_requires_relay_testloop(test);
292 
293 	kunit_activate_static_stub(test, relay_kick_worker, relay_process_incoming_action);
294 	kunit_activate_static_stub(test, xe_guc_ct_send_recv,
295 				   replacement_xe_guc_ct_send_recv_loopback_relay);
296 	ret = xe_guc_relay_send_to_vf(relay, TEST_VFID,
297 				      request, ARRAY_SIZE(request),
298 				      response, ARRAY_SIZE(response));
299 	KUNIT_ASSERT_EQ(test, ret, GUC_HXG_RESPONSE_MSG_MIN_LEN);
300 	KUNIT_EXPECT_EQ(test, FIELD_GET(GUC_HXG_MSG_0_ORIGIN, response[0]),
301 			GUC_HXG_ORIGIN_HOST);
302 	KUNIT_EXPECT_EQ(test, FIELD_GET(GUC_HXG_MSG_0_TYPE, response[0]),
303 			GUC_HXG_TYPE_RESPONSE_SUCCESS);
304 	KUNIT_EXPECT_EQ(test, FIELD_GET(GUC_HXG_RESPONSE_MSG_0_DATA0, response[0]), 0);
305 }
306 
pf_loopback_echo(struct kunit * test)307 static void pf_loopback_echo(struct kunit *test)
308 {
309 	struct xe_guc_relay *relay = test->priv;
310 	u32 request[] = {
311 		FIELD_PREP(GUC_HXG_MSG_0_ORIGIN, GUC_HXG_ORIGIN_HOST) |
312 		FIELD_PREP(GUC_HXG_MSG_0_TYPE, GUC_HXG_TYPE_REQUEST) |
313 		FIELD_PREP(GUC_HXG_REQUEST_MSG_0_ACTION, GUC_RELAY_ACTION_VFXPF_TESTLOOP) |
314 		FIELD_PREP(GUC_HXG_REQUEST_MSG_0_DATA0, VFXPF_TESTLOOP_OPCODE_ECHO),
315 		TEST_DATA(1), TEST_DATA(2), TEST_DATA(3), TEST_DATA(4),
316 	};
317 	u32 response[ARRAY_SIZE(request)];
318 	unsigned int n;
319 	int ret;
320 
321 	test_requires_relay_testloop(test);
322 
323 	kunit_activate_static_stub(test, relay_kick_worker, relay_process_incoming_action);
324 	kunit_activate_static_stub(test, xe_guc_ct_send_recv,
325 				   replacement_xe_guc_ct_send_recv_loopback_relay);
326 	ret = xe_guc_relay_send_to_vf(relay, TEST_VFID,
327 				      request, ARRAY_SIZE(request),
328 				      response, ARRAY_SIZE(response));
329 	KUNIT_ASSERT_EQ(test, ret, ARRAY_SIZE(response));
330 	KUNIT_EXPECT_EQ(test, FIELD_GET(GUC_HXG_MSG_0_ORIGIN, response[0]),
331 			GUC_HXG_ORIGIN_HOST);
332 	KUNIT_EXPECT_EQ(test, FIELD_GET(GUC_HXG_MSG_0_TYPE, response[0]),
333 			GUC_HXG_TYPE_RESPONSE_SUCCESS);
334 	KUNIT_EXPECT_EQ(test, FIELD_GET(GUC_HXG_RESPONSE_MSG_0_DATA0, response[0]),
335 			ARRAY_SIZE(response));
336 	for (n = GUC_HXG_RESPONSE_MSG_MIN_LEN; n < ret; n++)
337 		KUNIT_EXPECT_EQ(test, request[n], response[n]);
338 }
339 
pf_loopback_fail(struct kunit * test)340 static void pf_loopback_fail(struct kunit *test)
341 {
342 	struct xe_guc_relay *relay = test->priv;
343 	u32 request[] = {
344 		FIELD_PREP(GUC_HXG_MSG_0_ORIGIN, GUC_HXG_ORIGIN_HOST) |
345 		FIELD_PREP(GUC_HXG_MSG_0_TYPE, GUC_HXG_TYPE_REQUEST) |
346 		FIELD_PREP(GUC_HXG_REQUEST_MSG_0_ACTION, GUC_RELAY_ACTION_VFXPF_TESTLOOP) |
347 		FIELD_PREP(GUC_HXG_REQUEST_MSG_0_DATA0, VFXPF_TESTLOOP_OPCODE_FAIL),
348 	};
349 	u32 response[GUC_HXG_RESPONSE_MSG_MIN_LEN];
350 	int ret;
351 
352 	test_requires_relay_testloop(test);
353 
354 	kunit_activate_static_stub(test, relay_kick_worker, relay_process_incoming_action);
355 	kunit_activate_static_stub(test, xe_guc_ct_send_recv,
356 				   replacement_xe_guc_ct_send_recv_loopback_relay);
357 	ret = xe_guc_relay_send_to_vf(relay, TEST_VFID,
358 				      request, ARRAY_SIZE(request),
359 				      response, ARRAY_SIZE(response));
360 	KUNIT_ASSERT_EQ(test, ret, -EREMOTEIO);
361 }
362 
pf_loopback_busy(struct kunit * test)363 static void pf_loopback_busy(struct kunit *test)
364 {
365 	struct xe_guc_relay *relay = test->priv;
366 	u32 request[] = {
367 		FIELD_PREP(GUC_HXG_MSG_0_ORIGIN, GUC_HXG_ORIGIN_HOST) |
368 		FIELD_PREP(GUC_HXG_MSG_0_TYPE, GUC_HXG_TYPE_REQUEST) |
369 		FIELD_PREP(GUC_HXG_REQUEST_MSG_0_ACTION, GUC_RELAY_ACTION_VFXPF_TESTLOOP) |
370 		FIELD_PREP(GUC_HXG_REQUEST_MSG_0_DATA0, VFXPF_TESTLOOP_OPCODE_BUSY),
371 		TEST_DATA(0xb),
372 	};
373 	u32 response[GUC_HXG_RESPONSE_MSG_MIN_LEN];
374 	int ret;
375 
376 	test_requires_relay_testloop(test);
377 
378 	kunit_activate_static_stub(test, relay_testonly_nop, relay_process_incoming_action);
379 	kunit_activate_static_stub(test, relay_kick_worker, relay_process_incoming_action);
380 	kunit_activate_static_stub(test, xe_guc_ct_send_recv,
381 				   replacement_xe_guc_ct_send_recv_loopback_relay);
382 	ret = xe_guc_relay_send_to_vf(relay, TEST_VFID,
383 				      request, ARRAY_SIZE(request),
384 				      response, ARRAY_SIZE(response));
385 	KUNIT_ASSERT_EQ(test, ret, GUC_HXG_RESPONSE_MSG_MIN_LEN);
386 }
387 
pf_loopback_retry(struct kunit * test)388 static void pf_loopback_retry(struct kunit *test)
389 {
390 	struct xe_guc_relay *relay = test->priv;
391 	u32 request[] = {
392 		FIELD_PREP(GUC_HXG_MSG_0_ORIGIN, GUC_HXG_ORIGIN_HOST) |
393 		FIELD_PREP(GUC_HXG_MSG_0_TYPE, GUC_HXG_TYPE_REQUEST) |
394 		FIELD_PREP(GUC_HXG_REQUEST_MSG_0_ACTION, GUC_RELAY_ACTION_VFXPF_TESTLOOP) |
395 		FIELD_PREP(GUC_HXG_REQUEST_MSG_0_DATA0, VFXPF_TESTLOOP_OPCODE_RETRY),
396 		TEST_DATA(0xd), TEST_DATA(0xd),
397 	};
398 	u32 response[GUC_HXG_RESPONSE_MSG_MIN_LEN];
399 	int ret;
400 
401 	test_requires_relay_testloop(test);
402 
403 	kunit_activate_static_stub(test, relay_kick_worker, relay_process_incoming_action);
404 	kunit_activate_static_stub(test, xe_guc_ct_send_recv,
405 				   replacement_xe_guc_ct_send_recv_loopback_relay);
406 	ret = xe_guc_relay_send_to_vf(relay, TEST_VFID,
407 				      request, ARRAY_SIZE(request),
408 				      response, ARRAY_SIZE(response));
409 	KUNIT_ASSERT_EQ(test, ret, GUC_HXG_RESPONSE_MSG_MIN_LEN);
410 }
411 
412 static struct kunit_case pf_relay_test_cases[] = {
413 	KUNIT_CASE(pf_rejects_guc2pf_too_short),
414 	KUNIT_CASE(pf_rejects_guc2pf_too_long),
415 	KUNIT_CASE(pf_rejects_guc2pf_no_payload),
416 	KUNIT_CASE(pf_fails_no_payload),
417 	KUNIT_CASE(pf_fails_bad_origin),
418 	KUNIT_CASE(pf_fails_bad_type),
419 	KUNIT_CASE(pf_txn_reports_error),
420 	KUNIT_CASE(pf_txn_sends_pf2guc),
421 	KUNIT_CASE(pf_sends_pf2guc),
422 	KUNIT_CASE(pf_loopback_nop),
423 	KUNIT_CASE(pf_loopback_echo),
424 	KUNIT_CASE(pf_loopback_fail),
425 	KUNIT_CASE_SLOW(pf_loopback_busy),
426 	KUNIT_CASE_SLOW(pf_loopback_retry),
427 	{}
428 };
429 
430 static struct kunit_suite pf_relay_suite = {
431 	.name = "pf_relay",
432 	.test_cases = pf_relay_test_cases,
433 	.init = relay_test_init,
434 };
435 
vf_rejects_guc2vf_too_short(struct kunit * test)436 static void vf_rejects_guc2vf_too_short(struct kunit *test)
437 {
438 	const u32 len = GUC2VF_RELAY_FROM_PF_EVENT_MSG_MIN_LEN - 1;
439 	struct xe_guc_relay *relay = test->priv;
440 	const u32 *msg = test_guc2vf;
441 
442 	KUNIT_ASSERT_EQ(test, -EPROTO, xe_guc_relay_process_guc2vf(relay, msg, len));
443 }
444 
vf_rejects_guc2vf_too_long(struct kunit * test)445 static void vf_rejects_guc2vf_too_long(struct kunit *test)
446 {
447 	const u32 len = GUC2VF_RELAY_FROM_PF_EVENT_MSG_MAX_LEN + 1;
448 	struct xe_guc_relay *relay = test->priv;
449 	const u32 *msg = test_guc2vf;
450 
451 	KUNIT_ASSERT_EQ(test, -EMSGSIZE, xe_guc_relay_process_guc2vf(relay, msg, len));
452 }
453 
vf_rejects_guc2vf_no_payload(struct kunit * test)454 static void vf_rejects_guc2vf_no_payload(struct kunit *test)
455 {
456 	const u32 len = GUC2VF_RELAY_FROM_PF_EVENT_MSG_MIN_LEN;
457 	struct xe_guc_relay *relay = test->priv;
458 	const u32 *msg = test_guc2vf;
459 
460 	KUNIT_ASSERT_EQ(test, -EPROTO, xe_guc_relay_process_guc2vf(relay, msg, len));
461 }
462 
463 static struct kunit_case vf_relay_test_cases[] = {
464 	KUNIT_CASE(vf_rejects_guc2vf_too_short),
465 	KUNIT_CASE(vf_rejects_guc2vf_too_long),
466 	KUNIT_CASE(vf_rejects_guc2vf_no_payload),
467 	{}
468 };
469 
470 static struct kunit_suite vf_relay_suite = {
471 	.name = "vf_relay",
472 	.test_cases = vf_relay_test_cases,
473 	.init = relay_test_init,
474 };
475 
xe_drops_guc2pf_if_not_ready(struct kunit * test)476 static void xe_drops_guc2pf_if_not_ready(struct kunit *test)
477 {
478 	struct xe_device *xe = test->priv;
479 	struct xe_guc_relay *relay = &xe_device_get_gt(xe, 0)->uc.guc.relay;
480 	const u32 *msg = test_guc2pf;
481 	u32 len = GUC2PF_RELAY_FROM_VF_EVENT_MSG_MIN_LEN + GUC_RELAY_MSG_MIN_LEN;
482 
483 	KUNIT_ASSERT_EQ(test, -ENODEV, xe_guc_relay_process_guc2pf(relay, msg, len));
484 }
485 
xe_drops_guc2vf_if_not_ready(struct kunit * test)486 static void xe_drops_guc2vf_if_not_ready(struct kunit *test)
487 {
488 	struct xe_device *xe = test->priv;
489 	struct xe_guc_relay *relay = &xe_device_get_gt(xe, 0)->uc.guc.relay;
490 	const u32 *msg = test_guc2vf;
491 	u32 len = GUC2VF_RELAY_FROM_PF_EVENT_MSG_MIN_LEN + GUC_RELAY_MSG_MIN_LEN;
492 
493 	KUNIT_ASSERT_EQ(test, -ENODEV, xe_guc_relay_process_guc2vf(relay, msg, len));
494 }
495 
xe_rejects_send_if_not_ready(struct kunit * test)496 static void xe_rejects_send_if_not_ready(struct kunit *test)
497 {
498 	struct xe_device *xe = test->priv;
499 	struct xe_guc_relay *relay = &xe_device_get_gt(xe, 0)->uc.guc.relay;
500 	u32 msg[GUC_RELAY_MSG_MIN_LEN];
501 	u32 len = ARRAY_SIZE(msg);
502 
503 	KUNIT_ASSERT_EQ(test, -ENODEV, xe_guc_relay_send_to_pf(relay, msg, len, NULL, 0));
504 	KUNIT_ASSERT_EQ(test, -ENODEV, relay_send_to(relay, TEST_VFID, msg, len, NULL, 0));
505 }
506 
507 static struct kunit_case no_relay_test_cases[] = {
508 	KUNIT_CASE(xe_drops_guc2pf_if_not_ready),
509 	KUNIT_CASE(xe_drops_guc2vf_if_not_ready),
510 	KUNIT_CASE(xe_rejects_send_if_not_ready),
511 	{}
512 };
513 
514 static struct kunit_suite no_relay_suite = {
515 	.name = "no_relay",
516 	.test_cases = no_relay_test_cases,
517 	.init = xe_kunit_helper_xe_device_test_init,
518 };
519 
520 kunit_test_suites(&no_relay_suite,
521 		  &pf_relay_suite,
522 		  &vf_relay_suite);
523