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