xref: /linux/drivers/gpu/drm/xe/xe_uc.c (revision 7bdbfb4e36e34eb788e44f27666bf0a2b3b90803)
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 *
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 *
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 */
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  */
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 
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 
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 
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  */
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  */
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 
188 int xe_uc_fini_hw(struct xe_uc *uc)
189 {
190 	return xe_uc_sanitize_reset(uc);
191 }
192 
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 
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 
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 
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 
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 
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 
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