1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright �� 2021 Intel Corporation
4  */
5 
6 #include "selftests/intel_scheduler_helpers.h"
7 
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 
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 
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(&gt->uc))
124 		return 0;
125 
126 	return intel_gt_live_subtests(tests, gt);
127 }
128