Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/xe/kunit: Add GuC Relay kunit tests

Add few tests to make sure that some negative and normal use
scenarios of the GuC Relay are implemented correctly.

Reviewed-by: Piotr Piórkowski <piotr.piorkowski@intel.com>
Link: https://lore.kernel.org/r/20240104222031.277-10-michal.wajdeczko@intel.com
Signed-off-by: Michal Wajdeczko <michal.wajdeczko@intel.com>

+540 -3
+522
drivers/gpu/drm/xe/tests/xe_guc_relay_test.c
··· 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 + 20 + static int replacement_relay_get_totalvfs(struct xe_guc_relay *relay) 21 + { 22 + return TEST_VFID; 23 + } 24 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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);
+18 -3
drivers/gpu/drm/xe/xe_guc_relay.c
··· 8 8 9 9 #include <drm/drm_managed.h> 10 10 11 + #include <kunit/static_stub.h> 12 + 11 13 #include "abi/guc_actions_sriov_abi.h" 12 14 #include "abi/guc_relay_actions_abi.h" 13 15 #include "abi/guc_relay_communication_abi.h" ··· 62 60 struct xe_device *xe = relay_to_xe(relay); 63 61 struct pci_dev *pdev = to_pci_dev(xe->drm.dev); 64 62 63 + KUNIT_STATIC_STUB_REDIRECT(relay_get_totalvfs, relay); 65 64 return IS_SRIOV_VF(xe) ? 0 : pci_sriov_get_totalvfs(pdev); 66 65 } 67 66 ··· 395 392 return GUC_HXG_FAILURE_MSG_LEN; 396 393 } 397 394 395 + static void relay_testonly_nop(struct xe_guc_relay *relay) 396 + { 397 + KUNIT_STATIC_STUB_REDIRECT(relay_testonly_nop, relay); 398 + } 399 + 398 400 static int relay_send_message_and_wait(struct xe_guc_relay *relay, 399 401 struct relay_transaction *txn, 400 402 u32 *buf, u32 buf_size) ··· 442 434 reinit_completion(&txn->done); 443 435 if (txn->reply == -EAGAIN) 444 436 goto resend; 445 - if (txn->reply == -EBUSY) 437 + if (txn->reply == -EBUSY) { 438 + relay_testonly_nop(relay); 446 439 goto wait; 440 + } 447 441 if (txn->reply > 0) 448 442 ret = from_relay_error(txn->reply); 449 443 else ··· 761 751 762 752 static void relay_kick_worker(struct xe_guc_relay *relay) 763 753 { 754 + KUNIT_STATIC_STUB_REDIRECT(relay_kick_worker, relay); 764 755 queue_work(relay_to_xe(relay)->sriov.wq, &relay->worker); 765 756 } 766 757 ··· 860 849 relay_assert(relay, FIELD_GET(GUC_HXG_EVENT_MSG_0_ACTION, msg[0]) == 861 850 XE_GUC_ACTION_GUC2VF_RELAY_FROM_PF); 862 851 863 - if (unlikely(!IS_SRIOV_VF(relay_to_xe(relay)))) 852 + if (unlikely(!IS_SRIOV_VF(relay_to_xe(relay)) && !kunit_get_current_test())) 864 853 return -EPERM; 865 854 866 855 if (unlikely(!relay_is_ready(relay))) ··· 906 895 relay_assert(relay, FIELD_GET(GUC_HXG_EVENT_MSG_0_ACTION, msg[0]) == 907 896 XE_GUC_ACTION_GUC2PF_RELAY_FROM_VF); 908 897 909 - if (unlikely(!IS_SRIOV_PF(relay_to_xe(relay)))) 898 + if (unlikely(!IS_SRIOV_PF(relay_to_xe(relay)) && !kunit_get_current_test())) 910 899 return -EPERM; 911 900 912 901 if (unlikely(!relay_is_ready(relay))) ··· 933 922 934 923 return err; 935 924 } 925 + #endif 926 + 927 + #if IS_BUILTIN(CONFIG_DRM_XE_KUNIT_TEST) 928 + #include "tests/xe_guc_relay_test.c" 936 929 #endif