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