Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: MIT
2/*
3 * Copyright © 2022 Intel Corporation
4 */
5
6#include "xe_uc.h"
7
8#include "xe_assert.h"
9#include "xe_device.h"
10#include "xe_gsc.h"
11#include "xe_gt.h"
12#include "xe_gt_printk.h"
13#include "xe_gt_sriov_vf.h"
14#include "xe_guc.h"
15#include "xe_guc_pc.h"
16#include "xe_guc_rc.h"
17#include "xe_guc_engine_activity.h"
18#include "xe_huc.h"
19#include "xe_sriov.h"
20#include "xe_wopcm.h"
21
22static struct xe_gt *
23uc_to_gt(struct xe_uc *uc)
24{
25 return container_of(uc, struct xe_gt, uc);
26}
27
28static struct xe_device *
29uc_to_xe(struct xe_uc *uc)
30{
31 return gt_to_xe(uc_to_gt(uc));
32}
33
34/* Should be called once at driver load only */
35int xe_uc_init_noalloc(struct xe_uc *uc)
36{
37 int ret;
38
39 ret = xe_guc_init_noalloc(&uc->guc);
40 if (ret)
41 goto err;
42
43 /* HuC and GSC have no early dependencies and will be initialized during xe_uc_init(). */
44 return 0;
45
46err:
47 xe_gt_err(uc_to_gt(uc), "Failed to early initialize uC (%pe)\n", ERR_PTR(ret));
48 return ret;
49}
50
51int xe_uc_init(struct xe_uc *uc)
52{
53 int ret;
54
55 /*
56 * We call the GuC/HuC/GSC init functions even if GuC submission is off
57 * to correctly move our tracking of the FW state to "disabled".
58 */
59 ret = xe_guc_init(&uc->guc);
60 if (ret)
61 goto err;
62
63 ret = xe_huc_init(&uc->huc);
64 if (ret)
65 goto err;
66
67 ret = xe_gsc_init(&uc->gsc);
68 if (ret)
69 goto err;
70
71 if (!xe_device_uc_enabled(uc_to_xe(uc)))
72 return 0;
73
74 if (!IS_SRIOV_VF(uc_to_xe(uc))) {
75 ret = xe_wopcm_init(&uc->wopcm);
76 if (ret)
77 goto err;
78 }
79
80 ret = xe_guc_min_load_for_hwconfig(&uc->guc);
81 if (ret)
82 goto err;
83
84 return 0;
85err:
86 xe_gt_err(uc_to_gt(uc), "Failed to initialize uC (%pe)\n", ERR_PTR(ret));
87 return ret;
88}
89
90/**
91 * xe_uc_init_post_hwconfig - init Uc post hwconfig load
92 * @uc: The UC object
93 *
94 * Return: 0 on success, negative error code on error.
95 */
96int xe_uc_init_post_hwconfig(struct xe_uc *uc)
97{
98 int err;
99
100 /* GuC submission not enabled, nothing to do */
101 if (!xe_device_uc_enabled(uc_to_xe(uc)))
102 return 0;
103
104 err = xe_uc_sanitize_reset(uc);
105 if (err)
106 return err;
107
108 err = xe_guc_init_post_hwconfig(&uc->guc);
109 if (err)
110 return err;
111
112 err = xe_huc_init_post_hwconfig(&uc->huc);
113 if (err)
114 return err;
115
116 return xe_gsc_init_post_hwconfig(&uc->gsc);
117}
118
119static int uc_reset(struct xe_uc *uc)
120{
121 struct xe_device *xe = uc_to_xe(uc);
122 int ret;
123
124 ret = xe_guc_reset(&uc->guc);
125 if (ret) {
126 drm_err(&xe->drm, "Failed to reset GuC, ret = %d\n", ret);
127 return ret;
128 }
129
130 return 0;
131}
132
133static void xe_uc_sanitize(struct xe_uc *uc)
134{
135 xe_huc_sanitize(&uc->huc);
136 xe_guc_sanitize(&uc->guc);
137}
138
139int xe_uc_sanitize_reset(struct xe_uc *uc)
140{
141 xe_uc_sanitize(uc);
142
143 return uc_reset(uc);
144}
145
146static int vf_uc_load_hw(struct xe_uc *uc)
147{
148 int err;
149
150 err = xe_uc_sanitize_reset(uc);
151 if (err)
152 return err;
153
154 err = xe_guc_enable_communication(&uc->guc);
155 if (err)
156 return err;
157
158 err = xe_gt_sriov_vf_connect(uc_to_gt(uc));
159 if (err)
160 return err;
161
162 uc->guc.submission_state.enabled = true;
163
164 err = xe_guc_opt_in_features_enable(&uc->guc);
165 if (err)
166 return err;
167
168 err = xe_gt_record_default_lrcs(uc_to_gt(uc));
169 if (err)
170 return err;
171
172 return 0;
173}
174
175/*
176 * Should be called during driver load, after every GT reset, and after every
177 * suspend to reload / auth the firmwares.
178 */
179int xe_uc_load_hw(struct xe_uc *uc)
180{
181 int ret;
182
183 /* GuC submission not enabled, nothing to do */
184 if (!xe_device_uc_enabled(uc_to_xe(uc)))
185 return 0;
186
187 if (IS_SRIOV_VF(uc_to_xe(uc)))
188 return vf_uc_load_hw(uc);
189
190 ret = xe_huc_upload(&uc->huc);
191 if (ret)
192 return ret;
193
194 ret = xe_guc_upload(&uc->guc);
195 if (ret)
196 return ret;
197
198 ret = xe_guc_enable_communication(&uc->guc);
199 if (ret)
200 return ret;
201
202 ret = xe_gt_record_default_lrcs(uc_to_gt(uc));
203 if (ret)
204 return ret;
205
206 ret = xe_guc_post_load_init(&uc->guc);
207 if (ret)
208 return ret;
209
210 ret = xe_guc_pc_start(&uc->guc.pc);
211 if (ret)
212 return ret;
213
214 ret = xe_guc_rc_enable(&uc->guc);
215 if (ret)
216 return ret;
217
218 xe_guc_engine_activity_enable_stats(&uc->guc);
219
220 /* We don't fail the driver load if HuC fails to auth */
221 ret = xe_huc_auth(&uc->huc, XE_HUC_AUTH_VIA_GUC);
222 if (ret)
223 xe_gt_err(uc_to_gt(uc),
224 "HuC authentication failed (%pe), continuing with no HuC\n",
225 ERR_PTR(ret));
226
227 /* GSC load is async */
228 xe_gsc_load_start(&uc->gsc);
229
230 return 0;
231}
232
233int xe_uc_reset_prepare(struct xe_uc *uc)
234{
235 /* GuC submission not enabled, nothing to do */
236 if (!xe_device_uc_enabled(uc_to_xe(uc)))
237 return 0;
238
239 return xe_guc_reset_prepare(&uc->guc);
240}
241
242void xe_uc_stop_prepare(struct xe_uc *uc)
243{
244 xe_gsc_stop_prepare(&uc->gsc);
245 xe_guc_stop_prepare(&uc->guc);
246}
247
248void xe_uc_stop(struct xe_uc *uc)
249{
250 /* GuC submission not enabled, nothing to do */
251 if (!xe_device_uc_enabled(uc_to_xe(uc)))
252 return;
253
254 xe_guc_stop(&uc->guc);
255}
256
257int xe_uc_start(struct xe_uc *uc)
258{
259 /* GuC submission not enabled, nothing to do */
260 if (!xe_device_uc_enabled(uc_to_xe(uc)))
261 return 0;
262
263 return xe_guc_start(&uc->guc);
264}
265
266static void uc_reset_wait(struct xe_uc *uc)
267{
268 int ret;
269
270again:
271 xe_guc_reset_wait(&uc->guc);
272
273 ret = xe_uc_reset_prepare(uc);
274 if (ret)
275 goto again;
276}
277
278void xe_uc_suspend_prepare(struct xe_uc *uc)
279{
280 xe_gsc_wait_for_worker_completion(&uc->gsc);
281 xe_guc_stop_prepare(&uc->guc);
282}
283
284int xe_uc_suspend(struct xe_uc *uc)
285{
286 /* GuC submission not enabled, nothing to do */
287 if (!xe_device_uc_enabled(uc_to_xe(uc)))
288 return 0;
289
290 uc_reset_wait(uc);
291
292 xe_uc_stop(uc);
293
294 return xe_guc_suspend(&uc->guc);
295}
296
297/**
298 * xe_uc_runtime_suspend() - UC runtime suspend
299 * @uc: the UC object
300 *
301 * Runtime suspend all UCs.
302 */
303void xe_uc_runtime_suspend(struct xe_uc *uc)
304{
305 if (!xe_device_uc_enabled(uc_to_xe(uc)))
306 return;
307
308 xe_guc_runtime_suspend(&uc->guc);
309}
310
311/**
312 * xe_uc_runtime_resume() - UC runtime resume
313 * @uc: the UC object
314 *
315 * Runtime resume all UCs.
316 */
317void xe_uc_runtime_resume(struct xe_uc *uc)
318{
319 if (!xe_device_uc_enabled(uc_to_xe(uc)))
320 return;
321
322 xe_guc_runtime_resume(&uc->guc);
323}
324
325/**
326 * xe_uc_declare_wedged() - Declare UC wedged
327 * @uc: the UC object
328 *
329 * Wedge the UC which stops all submission, saves desired debug state, and
330 * cleans up anything which could timeout.
331 */
332void xe_uc_declare_wedged(struct xe_uc *uc)
333{
334 xe_gt_assert(uc_to_gt(uc), uc_to_xe(uc)->wedged.mode);
335
336 xe_guc_declare_wedged(&uc->guc);
337}