1 // SPDX-License-Identifier: MIT
2 /*
3 * Copyright �� 2021 Intel Corporation
4 */
5
6 #include "selftests/intel_scheduler_helpers.h"
7
nop_user_request(struct intel_context * ce,struct i915_request * from)8 static struct i915_request *nop_user_request(struct intel_context *ce,
9 struct i915_request *from)
10 {
11 struct i915_request *rq;
12 int ret;
13
14 rq = intel_context_create_request(ce);
15 if (IS_ERR(rq))
16 return rq;
17
18 if (from) {
19 ret = i915_sw_fence_await_dma_fence(&rq->submit,
20 &from->fence, 0,
21 I915_FENCE_GFP);
22 if (ret < 0) {
23 i915_request_put(rq);
24 return ERR_PTR(ret);
25 }
26 }
27
28 i915_request_get(rq);
29 i915_request_add(rq);
30
31 return rq;
32 }
33
intel_guc_scrub_ctbs(void * arg)34 static int intel_guc_scrub_ctbs(void *arg)
35 {
36 struct intel_gt *gt = arg;
37 int ret = 0;
38 int i;
39 struct i915_request *last[3] = {NULL, NULL, NULL}, *rq;
40 intel_wakeref_t wakeref;
41 struct intel_engine_cs *engine;
42 struct intel_context *ce;
43
44 wakeref = intel_runtime_pm_get(gt->uncore->rpm);
45 engine = intel_selftest_find_any_engine(gt);
46
47 /* Submit requests and inject errors forcing G2H to be dropped */
48 for (i = 0; i < 3; ++i) {
49 ce = intel_context_create(engine);
50 if (IS_ERR(ce)) {
51 ret = PTR_ERR(ce);
52 pr_err("Failed to create context, %d: %d\n", i, ret);
53 goto err;
54 }
55
56 switch (i) {
57 case 0:
58 ce->drop_schedule_enable = true;
59 break;
60 case 1:
61 ce->drop_schedule_disable = true;
62 break;
63 case 2:
64 ce->drop_deregister = true;
65 break;
66 }
67
68 rq = nop_user_request(ce, NULL);
69 intel_context_put(ce);
70
71 if (IS_ERR(rq)) {
72 ret = PTR_ERR(rq);
73 pr_err("Failed to create request, %d: %d\n", i, ret);
74 goto err;
75 }
76
77 last[i] = rq;
78 }
79
80 for (i = 0; i < 3; ++i) {
81 ret = i915_request_wait(last[i], 0, HZ);
82 if (ret < 0) {
83 pr_err("Last request failed to complete: %d\n", ret);
84 goto err;
85 }
86 i915_request_put(last[i]);
87 last[i] = NULL;
88 }
89
90 /* Force all H2G / G2H to be submitted / processed */
91 intel_gt_retire_requests(gt);
92 msleep(500);
93
94 /* Scrub missing G2H */
95 intel_gt_handle_error(engine->gt, -1, 0, "selftest reset");
96
97 /* GT will not idle if G2H are lost */
98 ret = intel_gt_wait_for_idle(gt, HZ);
99 if (ret < 0) {
100 pr_err("GT failed to idle: %d\n", ret);
101 goto err;
102 }
103
104 err:
105 for (i = 0; i < 3; ++i)
106 if (last[i])
107 i915_request_put(last[i]);
108 intel_runtime_pm_put(gt->uncore->rpm, wakeref);
109
110 return ret;
111 }
112
intel_guc_live_selftests(struct drm_i915_private * i915)113 int intel_guc_live_selftests(struct drm_i915_private *i915)
114 {
115 static const struct i915_subtest tests[] = {
116 SUBTEST(intel_guc_scrub_ctbs),
117 };
118 struct intel_gt *gt = &i915->gt;
119
120 if (intel_gt_is_wedged(gt))
121 return 0;
122
123 if (!intel_uc_uses_guc_submission(>->uc))
124 return 0;
125
126 return intel_gt_live_subtests(tests, gt);
127 }
128