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