Loading...
Note: File does not exist in v4.6.
1// SPDX-License-Identifier: MIT
2/*
3 * Copyright © 2022 Intel Corporation
4 */
5
6#include "selftests/igt_spinner.h"
7#include "selftests/igt_reset.h"
8#include "selftests/intel_scheduler_helpers.h"
9#include "gt/intel_engine_heartbeat.h"
10#include "gem/selftests/mock_context.h"
11
12#define BEAT_INTERVAL 100
13
14static struct i915_request *nop_request(struct intel_engine_cs *engine)
15{
16 struct i915_request *rq;
17
18 rq = intel_engine_create_kernel_request(engine);
19 if (IS_ERR(rq))
20 return rq;
21
22 i915_request_get(rq);
23 i915_request_add(rq);
24
25 return rq;
26}
27
28static int intel_hang_guc(void *arg)
29{
30 struct intel_gt *gt = arg;
31 int ret = 0;
32 struct i915_gem_context *ctx;
33 struct intel_context *ce;
34 struct igt_spinner spin;
35 struct i915_request *rq;
36 intel_wakeref_t wakeref;
37 struct i915_gpu_error *global = >->i915->gpu_error;
38 struct intel_engine_cs *engine = intel_selftest_find_any_engine(gt);
39 unsigned int reset_count;
40 u32 guc_status;
41 u32 old_beat;
42
43 if (!engine)
44 return 0;
45
46 ctx = kernel_context(gt->i915, NULL);
47 if (IS_ERR(ctx)) {
48 drm_err(>->i915->drm, "Failed get kernel context: %ld\n", PTR_ERR(ctx));
49 return PTR_ERR(ctx);
50 }
51
52 wakeref = intel_runtime_pm_get(gt->uncore->rpm);
53
54 ce = intel_context_create(engine);
55 if (IS_ERR(ce)) {
56 ret = PTR_ERR(ce);
57 drm_err(>->i915->drm, "Failed to create spinner request: %d\n", ret);
58 goto err;
59 }
60
61 reset_count = i915_reset_count(global);
62
63 old_beat = engine->props.heartbeat_interval_ms;
64 ret = intel_engine_set_heartbeat(engine, BEAT_INTERVAL);
65 if (ret) {
66 drm_err(>->i915->drm, "Failed to boost heatbeat interval: %d\n", ret);
67 goto err;
68 }
69
70 ret = igt_spinner_init(&spin, engine->gt);
71 if (ret) {
72 drm_err(>->i915->drm, "Failed to create spinner: %d\n", ret);
73 goto err;
74 }
75
76 rq = igt_spinner_create_request(&spin, ce, MI_NOOP);
77 intel_context_put(ce);
78 if (IS_ERR(rq)) {
79 ret = PTR_ERR(rq);
80 drm_err(>->i915->drm, "Failed to create spinner request: %d\n", ret);
81 goto err_spin;
82 }
83
84 ret = request_add_spin(rq, &spin);
85 if (ret) {
86 i915_request_put(rq);
87 drm_err(>->i915->drm, "Failed to add Spinner request: %d\n", ret);
88 goto err_spin;
89 }
90
91 ret = intel_reset_guc(gt);
92 if (ret) {
93 i915_request_put(rq);
94 drm_err(>->i915->drm, "Failed to reset GuC, ret = %d\n", ret);
95 goto err_spin;
96 }
97
98 guc_status = intel_uncore_read(gt->uncore, GUC_STATUS);
99 if (!(guc_status & GS_MIA_IN_RESET)) {
100 i915_request_put(rq);
101 drm_err(>->i915->drm, "GuC failed to reset: status = 0x%08X\n", guc_status);
102 ret = -EIO;
103 goto err_spin;
104 }
105
106 /* Wait for the heartbeat to cause a reset */
107 ret = intel_selftest_wait_for_rq(rq);
108 i915_request_put(rq);
109 if (ret) {
110 drm_err(>->i915->drm, "Request failed to complete: %d\n", ret);
111 goto err_spin;
112 }
113
114 if (i915_reset_count(global) == reset_count) {
115 drm_err(>->i915->drm, "Failed to record a GPU reset\n");
116 ret = -EINVAL;
117 goto err_spin;
118 }
119
120err_spin:
121 igt_spinner_end(&spin);
122 igt_spinner_fini(&spin);
123 intel_engine_set_heartbeat(engine, old_beat);
124
125 if (ret == 0) {
126 rq = nop_request(engine);
127 if (IS_ERR(rq)) {
128 ret = PTR_ERR(rq);
129 goto err;
130 }
131
132 ret = intel_selftest_wait_for_rq(rq);
133 i915_request_put(rq);
134 if (ret) {
135 drm_err(>->i915->drm, "No-op failed to complete: %d\n", ret);
136 goto err;
137 }
138 }
139
140err:
141 intel_runtime_pm_put(gt->uncore->rpm, wakeref);
142 kernel_context_close(ctx);
143
144 return ret;
145}
146
147int intel_guc_hang_check(struct drm_i915_private *i915)
148{
149 static const struct i915_subtest tests[] = {
150 SUBTEST(intel_hang_guc),
151 };
152 struct intel_gt *gt = to_gt(i915);
153
154 if (intel_gt_is_wedged(gt))
155 return 0;
156
157 if (!intel_uc_uses_guc_submission(>->uc))
158 return 0;
159
160 return intel_gt_live_subtests(tests, gt);
161}