1 // SPDX-License-Identifier: MIT
2 /*
3 * Copyright © 2022 Intel Corporation
4 */
5
6 #include "xe_uc.h"
7
8 #include "xe_device.h"
9 #include "xe_gsc.h"
10 #include "xe_gt.h"
11 #include "xe_guc.h"
12 #include "xe_guc_pc.h"
13 #include "xe_guc_submit.h"
14 #include "xe_huc.h"
15 #include "xe_uc_fw.h"
16 #include "xe_wopcm.h"
17
18 static struct xe_gt *
uc_to_gt(struct xe_uc * uc)19 uc_to_gt(struct xe_uc *uc)
20 {
21 return container_of(uc, struct xe_gt, uc);
22 }
23
24 static struct xe_device *
uc_to_xe(struct xe_uc * uc)25 uc_to_xe(struct xe_uc *uc)
26 {
27 return gt_to_xe(uc_to_gt(uc));
28 }
29
30 /* Should be called once at driver load only */
xe_uc_init(struct xe_uc * uc)31 int xe_uc_init(struct xe_uc *uc)
32 {
33 int ret;
34
35 /*
36 * We call the GuC/HuC/GSC init functions even if GuC submission is off
37 * to correctly move our tracking of the FW state to "disabled".
38 */
39
40 ret = xe_guc_init(&uc->guc);
41 if (ret)
42 goto err;
43
44 ret = xe_huc_init(&uc->huc);
45 if (ret)
46 goto err;
47
48 ret = xe_gsc_init(&uc->gsc);
49 if (ret)
50 goto err;
51
52 if (!xe_device_uc_enabled(uc_to_xe(uc)))
53 return 0;
54
55 ret = xe_wopcm_init(&uc->wopcm);
56 if (ret)
57 goto err;
58
59 ret = xe_guc_submit_init(&uc->guc);
60 if (ret)
61 goto err;
62
63 return 0;
64
65 err:
66 return ret;
67 }
68
69 /**
70 * xe_uc_init_post_hwconfig - init Uc post hwconfig load
71 * @uc: The UC object
72 *
73 * Return: 0 on success, negative error code on error.
74 */
xe_uc_init_post_hwconfig(struct xe_uc * uc)75 int xe_uc_init_post_hwconfig(struct xe_uc *uc)
76 {
77 int err;
78
79 /* GuC submission not enabled, nothing to do */
80 if (!xe_device_uc_enabled(uc_to_xe(uc)))
81 return 0;
82
83 err = xe_uc_sanitize_reset(uc);
84 if (err)
85 return err;
86
87 err = xe_guc_init_post_hwconfig(&uc->guc);
88 if (err)
89 return err;
90
91 return xe_gsc_init_post_hwconfig(&uc->gsc);
92 }
93
uc_reset(struct xe_uc * uc)94 static int uc_reset(struct xe_uc *uc)
95 {
96 struct xe_device *xe = uc_to_xe(uc);
97 int ret;
98
99 ret = xe_guc_reset(&uc->guc);
100 if (ret) {
101 drm_err(&xe->drm, "Failed to reset GuC, ret = %d\n", ret);
102 return ret;
103 }
104
105 return 0;
106 }
107
xe_uc_sanitize(struct xe_uc * uc)108 static void xe_uc_sanitize(struct xe_uc *uc)
109 {
110 xe_huc_sanitize(&uc->huc);
111 xe_guc_sanitize(&uc->guc);
112 }
113
xe_uc_sanitize_reset(struct xe_uc * uc)114 int xe_uc_sanitize_reset(struct xe_uc *uc)
115 {
116 xe_uc_sanitize(uc);
117
118 return uc_reset(uc);
119 }
120
121 /**
122 * xe_uc_init_hwconfig - minimally init Uc, read and parse hwconfig
123 * @uc: The UC object
124 *
125 * Return: 0 on success, negative error code on error.
126 */
xe_uc_init_hwconfig(struct xe_uc * uc)127 int xe_uc_init_hwconfig(struct xe_uc *uc)
128 {
129 int ret;
130
131 /* GuC submission not enabled, nothing to do */
132 if (!xe_device_uc_enabled(uc_to_xe(uc)))
133 return 0;
134
135 ret = xe_guc_min_load_for_hwconfig(&uc->guc);
136 if (ret)
137 return ret;
138
139 return 0;
140 }
141
142 /*
143 * Should be called during driver load, after every GT reset, and after every
144 * suspend to reload / auth the firmwares.
145 */
xe_uc_init_hw(struct xe_uc * uc)146 int xe_uc_init_hw(struct xe_uc *uc)
147 {
148 int ret;
149
150 /* GuC submission not enabled, nothing to do */
151 if (!xe_device_uc_enabled(uc_to_xe(uc)))
152 return 0;
153
154 ret = xe_huc_upload(&uc->huc);
155 if (ret)
156 return ret;
157
158 ret = xe_guc_upload(&uc->guc);
159 if (ret)
160 return ret;
161
162 ret = xe_guc_enable_communication(&uc->guc);
163 if (ret)
164 return ret;
165
166 ret = xe_gt_record_default_lrcs(uc_to_gt(uc));
167 if (ret)
168 return ret;
169
170 ret = xe_guc_post_load_init(&uc->guc);
171 if (ret)
172 return ret;
173
174 ret = xe_guc_pc_start(&uc->guc.pc);
175 if (ret)
176 return ret;
177
178 /* We don't fail the driver load if HuC fails to auth, but let's warn */
179 ret = xe_huc_auth(&uc->huc, XE_HUC_AUTH_VIA_GUC);
180 xe_gt_assert(uc_to_gt(uc), !ret);
181
182 /* GSC load is async */
183 xe_gsc_load_start(&uc->gsc);
184
185 return 0;
186 }
187
xe_uc_fini_hw(struct xe_uc * uc)188 int xe_uc_fini_hw(struct xe_uc *uc)
189 {
190 return xe_uc_sanitize_reset(uc);
191 }
192
xe_uc_reset_prepare(struct xe_uc * uc)193 int xe_uc_reset_prepare(struct xe_uc *uc)
194 {
195 /* GuC submission not enabled, nothing to do */
196 if (!xe_device_uc_enabled(uc_to_xe(uc)))
197 return 0;
198
199 return xe_guc_reset_prepare(&uc->guc);
200 }
201
xe_uc_gucrc_disable(struct xe_uc * uc)202 void xe_uc_gucrc_disable(struct xe_uc *uc)
203 {
204 XE_WARN_ON(xe_guc_pc_gucrc_disable(&uc->guc.pc));
205 }
206
xe_uc_stop_prepare(struct xe_uc * uc)207 void xe_uc_stop_prepare(struct xe_uc *uc)
208 {
209 xe_gsc_wait_for_worker_completion(&uc->gsc);
210 xe_guc_stop_prepare(&uc->guc);
211 }
212
xe_uc_stop(struct xe_uc * uc)213 int xe_uc_stop(struct xe_uc *uc)
214 {
215 /* GuC submission not enabled, nothing to do */
216 if (!xe_device_uc_enabled(uc_to_xe(uc)))
217 return 0;
218
219 return xe_guc_stop(&uc->guc);
220 }
221
xe_uc_start(struct xe_uc * uc)222 int xe_uc_start(struct xe_uc *uc)
223 {
224 /* GuC submission not enabled, nothing to do */
225 if (!xe_device_uc_enabled(uc_to_xe(uc)))
226 return 0;
227
228 return xe_guc_start(&uc->guc);
229 }
230
uc_reset_wait(struct xe_uc * uc)231 static void uc_reset_wait(struct xe_uc *uc)
232 {
233 int ret;
234
235 again:
236 xe_guc_reset_wait(&uc->guc);
237
238 ret = xe_uc_reset_prepare(uc);
239 if (ret)
240 goto again;
241 }
242
xe_uc_suspend(struct xe_uc * uc)243 int xe_uc_suspend(struct xe_uc *uc)
244 {
245 int ret;
246
247 /* GuC submission not enabled, nothing to do */
248 if (!xe_device_uc_enabled(uc_to_xe(uc)))
249 return 0;
250
251 uc_reset_wait(uc);
252
253 ret = xe_uc_stop(uc);
254 if (ret)
255 return ret;
256
257 return xe_guc_suspend(&uc->guc);
258 }
259