Skip to content

Commit 706785c

Browse files
drm/i915/guc: Add a selftest for FAST_REQUEST errors
There is a mechanism for reporting errors from fire and forget H2G messages. This is the only way to find out about almost any error in the GuC backend submission path. So it would be useful to know that it is working. v2: Fix some dumb over-complications and a couple of typos - review feedback from Daniele. Signed-off-by: John Harrison <[email protected]> Reviewed-by: Daniele Ceraolo Spurio <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent b7d2a4d commit 706785c

File tree

3 files changed

+128
-0
lines changed

3 files changed

+128
-0
lines changed

drivers/gpu/drm/i915/gt/uc/intel_guc.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,10 @@ struct intel_guc {
297297
* @number_guc_id_stolen: The number of guc_ids that have been stolen
298298
*/
299299
int number_guc_id_stolen;
300+
/**
301+
* @fast_response_selftest: Backdoor to CT handler for fast response selftest
302+
*/
303+
u32 fast_response_selftest;
300304
#endif
301305
};
302306

drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,6 +1076,15 @@ static int ct_handle_response(struct intel_guc_ct *ct, struct ct_incoming_msg *r
10761076
found = true;
10771077
break;
10781078
}
1079+
1080+
#ifdef CONFIG_DRM_I915_SELFTEST
1081+
if (!found && ct_to_guc(ct)->fast_response_selftest) {
1082+
CT_DEBUG(ct, "Assuming unsolicited response due to FAST_REQUEST selftest\n");
1083+
ct_to_guc(ct)->fast_response_selftest++;
1084+
found = true;
1085+
}
1086+
#endif
1087+
10791088
if (!found) {
10801089
CT_ERROR(ct, "Unsolicited response message: len %u, data %#x (fence %u, last %u)\n",
10811090
len, hxg[0], fence, ct->requests.last_fence);

drivers/gpu/drm/i915/gt/uc/selftest_guc.c

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,11 +286,126 @@ static int intel_guc_steal_guc_ids(void *arg)
286286
return ret;
287287
}
288288

289+
/*
290+
* Send a context schedule H2G message with an invalid context id.
291+
* This should generate a GUC_RESULT_INVALID_CONTEXT response.
292+
*/
293+
static int bad_h2g(struct intel_guc *guc)
294+
{
295+
u32 action[] = {
296+
INTEL_GUC_ACTION_SCHED_CONTEXT,
297+
0x12345678,
298+
};
299+
300+
return intel_guc_send_nb(guc, action, ARRAY_SIZE(action), 0);
301+
}
302+
303+
/*
304+
* Set a spinner running to make sure the system is alive and active,
305+
* then send a bad but asynchronous H2G command and wait to see if an
306+
* error response is returned. If no response is received or if the
307+
* spinner dies then the test will fail.
308+
*/
309+
#define FAST_RESPONSE_TIMEOUT_MS 1000
310+
static int intel_guc_fast_request(void *arg)
311+
{
312+
struct intel_gt *gt = arg;
313+
struct intel_context *ce;
314+
struct igt_spinner spin;
315+
struct i915_request *rq;
316+
intel_wakeref_t wakeref;
317+
struct intel_engine_cs *engine = intel_selftest_find_any_engine(gt);
318+
bool spinning = false;
319+
int ret = 0;
320+
321+
if (!engine)
322+
return 0;
323+
324+
wakeref = intel_runtime_pm_get(gt->uncore->rpm);
325+
326+
ce = intel_context_create(engine);
327+
if (IS_ERR(ce)) {
328+
ret = PTR_ERR(ce);
329+
gt_err(gt, "Failed to create spinner request: %pe\n", ce);
330+
goto err_pm;
331+
}
332+
333+
ret = igt_spinner_init(&spin, engine->gt);
334+
if (ret) {
335+
gt_err(gt, "Failed to create spinner: %pe\n", ERR_PTR(ret));
336+
goto err_pm;
337+
}
338+
spinning = true;
339+
340+
rq = igt_spinner_create_request(&spin, ce, MI_ARB_CHECK);
341+
intel_context_put(ce);
342+
if (IS_ERR(rq)) {
343+
ret = PTR_ERR(rq);
344+
gt_err(gt, "Failed to create spinner request: %pe\n", rq);
345+
goto err_spin;
346+
}
347+
348+
ret = request_add_spin(rq, &spin);
349+
if (ret) {
350+
gt_err(gt, "Failed to add Spinner request: %pe\n", ERR_PTR(ret));
351+
goto err_rq;
352+
}
353+
354+
gt->uc.guc.fast_response_selftest = 1;
355+
356+
ret = bad_h2g(&gt->uc.guc);
357+
if (ret) {
358+
gt_err(gt, "Failed to send H2G: %pe\n", ERR_PTR(ret));
359+
goto err_rq;
360+
}
361+
362+
ret = wait_for(gt->uc.guc.fast_response_selftest != 1 || i915_request_completed(rq),
363+
FAST_RESPONSE_TIMEOUT_MS);
364+
if (ret) {
365+
gt_err(gt, "Request wait failed: %pe\n", ERR_PTR(ret));
366+
goto err_rq;
367+
}
368+
369+
if (i915_request_completed(rq)) {
370+
gt_err(gt, "Spinner died waiting for fast request error!\n");
371+
ret = -EIO;
372+
goto err_rq;
373+
}
374+
375+
if (gt->uc.guc.fast_response_selftest != 2) {
376+
gt_err(gt, "Unexpected fast response count: %d\n",
377+
gt->uc.guc.fast_response_selftest);
378+
goto err_rq;
379+
}
380+
381+
igt_spinner_end(&spin);
382+
spinning = false;
383+
384+
ret = intel_selftest_wait_for_rq(rq);
385+
if (ret) {
386+
gt_err(gt, "Request failed to complete: %pe\n", ERR_PTR(ret));
387+
goto err_rq;
388+
}
389+
390+
err_rq:
391+
i915_request_put(rq);
392+
393+
err_spin:
394+
if (spinning)
395+
igt_spinner_end(&spin);
396+
igt_spinner_fini(&spin);
397+
398+
err_pm:
399+
intel_runtime_pm_put(gt->uncore->rpm, wakeref);
400+
return ret;
401+
}
402+
289403
int intel_guc_live_selftests(struct drm_i915_private *i915)
290404
{
291405
static const struct i915_subtest tests[] = {
292406
SUBTEST(intel_guc_scrub_ctbs),
293407
SUBTEST(intel_guc_steal_guc_ids),
408+
SUBTEST(intel_guc_fast_request),
294409
};
295410
struct intel_gt *gt = to_gt(i915);
296411

0 commit comments

Comments
 (0)