blob: d82ca0f438f5296aebe208d5d50622cecb731a0c [file] [log] [blame]
Arkadiusz Hiler2d803c22016-11-25 18:59:35 +01001/*
2 * Copyright © 2016 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 *
23 */
24
Arkadiusz Hiler2d803c22016-11-25 18:59:35 +010025#include "intel_uc.h"
Sagar Arun Kamblea2695742017-11-16 19:02:41 +053026#include "intel_guc_submission.h"
Michał Winiarski1bbbca02017-12-13 23:13:46 +010027#include "intel_guc.h"
Michal Wajdeczkoddf79d82017-10-04 18:13:42 +000028#include "i915_drv.h"
Arkadiusz Hiler2d803c22016-11-25 18:59:35 +010029
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +010030/* Reset GuC providing us with fresh state for both GuC and HuC.
31 */
32static int __intel_uc_reset_hw(struct drm_i915_private *dev_priv)
33{
34 int ret;
35 u32 guc_status;
36
Michel Thierrycb20a3c2017-10-30 11:56:14 -070037 ret = intel_reset_guc(dev_priv);
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +010038 if (ret) {
Michel Thierrycb20a3c2017-10-30 11:56:14 -070039 DRM_ERROR("Failed to reset GuC, ret = %d\n", ret);
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +010040 return ret;
41 }
42
43 guc_status = I915_READ(GUC_STATUS);
44 WARN(!(guc_status & GS_MIA_IN_RESET),
45 "GuC status: 0x%x, MIA core expected to be in reset\n",
46 guc_status);
47
48 return ret;
49}
50
Michal Wajdeczko121981f2017-12-06 13:53:15 +000051static int __get_platform_enable_guc(struct drm_i915_private *dev_priv)
52{
53 struct intel_uc_fw *guc_fw = &dev_priv->guc.fw;
54 struct intel_uc_fw *huc_fw = &dev_priv->huc.fw;
55 int enable_guc = 0;
56
57 /* Default is to enable GuC/HuC if we know their firmwares */
58 if (intel_uc_fw_is_selected(guc_fw))
59 enable_guc |= ENABLE_GUC_SUBMISSION;
60 if (intel_uc_fw_is_selected(huc_fw))
61 enable_guc |= ENABLE_GUC_LOAD_HUC;
62
63 /* Any platform specific fine-tuning can be done here */
64
65 return enable_guc;
66}
67
68/**
69 * intel_uc_sanitize_options - sanitize uC related modparam options
70 * @dev_priv: device private
71 *
72 * In case of "enable_guc" option this function will attempt to modify
73 * it only if it was initially set to "auto(-1)". Default value for this
74 * modparam varies between platforms and it is hardcoded in driver code.
75 * Any other modparam value is only monitored against availability of the
76 * related hardware or firmware definitions.
77 */
Arkadiusz Hilerd2be9f22017-03-14 15:28:10 +010078void intel_uc_sanitize_options(struct drm_i915_private *dev_priv)
79{
Michal Wajdeczko121981f2017-12-06 13:53:15 +000080 struct intel_uc_fw *guc_fw = &dev_priv->guc.fw;
81 struct intel_uc_fw *huc_fw = &dev_priv->huc.fw;
Arkadiusz Hilerb551f612017-03-14 15:28:13 +010082
Michal Wajdeczkod4a70a12017-03-15 13:37:41 +000083 /* A negative value means "use platform default" */
Michal Wajdeczko121981f2017-12-06 13:53:15 +000084 if (i915_modparams.enable_guc < 0)
85 i915_modparams.enable_guc = __get_platform_enable_guc(dev_priv);
Michal Wajdeczkod4a70a12017-03-15 13:37:41 +000086
Michal Wajdeczko121981f2017-12-06 13:53:15 +000087 DRM_DEBUG_DRIVER("enable_guc=%d (submission:%s huc:%s)\n",
88 i915_modparams.enable_guc,
89 yesno(intel_uc_is_using_guc_submission()),
90 yesno(intel_uc_is_using_huc()));
91
92 /* Verify GuC firmware availability */
93 if (intel_uc_is_using_guc() && !intel_uc_fw_is_selected(guc_fw)) {
94 DRM_WARN("Incompatible option detected: enable_guc=%d, %s!\n",
95 i915_modparams.enable_guc,
96 !HAS_GUC(dev_priv) ? "no GuC hardware" :
97 "no GuC firmware");
Arkadiusz Hilerb551f612017-03-14 15:28:13 +010098 }
Michal Wajdeczkod4a70a12017-03-15 13:37:41 +000099
Michal Wajdeczko121981f2017-12-06 13:53:15 +0000100 /* Verify HuC firmware availability */
101 if (intel_uc_is_using_huc() && !intel_uc_fw_is_selected(huc_fw)) {
102 DRM_WARN("Incompatible option detected: enable_guc=%d, %s!\n",
103 i915_modparams.enable_guc,
104 !HAS_HUC(dev_priv) ? "no HuC hardware" :
105 "no HuC firmware");
106 }
Michal Wajdeczkod4a70a12017-03-15 13:37:41 +0000107
Michal Wajdeczko121981f2017-12-06 13:53:15 +0000108 /* Make sure that sanitization was done */
109 GEM_BUG_ON(i915_modparams.enable_guc < 0);
Arkadiusz Hilerd2be9f22017-03-14 15:28:10 +0100110}
111
Michal Wajdeczko3af7a9c2017-10-04 15:33:27 +0000112void intel_uc_init_early(struct drm_i915_private *dev_priv)
113{
Michal Wajdeczko9bf384c2017-10-04 18:13:41 +0000114 intel_guc_init_early(&dev_priv->guc);
Michal Wajdeczko2fe2d4e2017-12-06 13:53:10 +0000115 intel_huc_init_early(&dev_priv->huc);
Michal Wajdeczko3af7a9c2017-10-04 15:33:27 +0000116}
117
Arkadiusz Hiler29ad6a32017-03-14 15:28:09 +0100118void intel_uc_init_fw(struct drm_i915_private *dev_priv)
119{
Michal Wajdeczkoa655aeb2017-12-06 13:53:13 +0000120 if (!USES_GUC(dev_priv))
121 return;
122
Michal Wajdeczko0dfa1ce2017-12-06 13:53:16 +0000123 if (USES_HUC(dev_priv))
124 intel_uc_fw_fetch(dev_priv, &dev_priv->huc.fw);
125
Michal Wajdeczkoa16b4312017-10-04 15:33:25 +0000126 intel_uc_fw_fetch(dev_priv, &dev_priv->guc.fw);
Arkadiusz Hiler29ad6a32017-03-14 15:28:09 +0100127}
128
Oscar Mateo3950bf32017-03-22 10:39:46 -0700129void intel_uc_fini_fw(struct drm_i915_private *dev_priv)
130{
Michal Wajdeczkoa655aeb2017-12-06 13:53:13 +0000131 if (!USES_GUC(dev_priv))
132 return;
133
Michal Wajdeczkoa16b4312017-10-04 15:33:25 +0000134 intel_uc_fw_fini(&dev_priv->guc.fw);
Michal Wajdeczko0dfa1ce2017-12-06 13:53:16 +0000135
136 if (USES_HUC(dev_priv))
137 intel_uc_fw_fini(&dev_priv->huc.fw);
Oscar Mateo3950bf32017-03-22 10:39:46 -0700138}
139
Sagar Arun Kamble1fc556f2017-10-04 15:33:24 +0000140/**
141 * intel_uc_init_mmio - setup uC MMIO access
142 *
143 * @dev_priv: device private
144 *
145 * Setup minimal state necessary for MMIO accesses later in the
146 * initialization sequence.
147 */
148void intel_uc_init_mmio(struct drm_i915_private *dev_priv)
149{
Michal Wajdeczko9bf384c2017-10-04 18:13:41 +0000150 intel_guc_init_send_regs(&dev_priv->guc);
Sagar Arun Kamble1fc556f2017-10-04 15:33:24 +0000151}
152
Daniele Ceraolo Spurioac58d2a2017-05-22 10:50:28 -0700153static void guc_capture_load_err_log(struct intel_guc *guc)
154{
Michal Wajdeczko4f044a82017-09-19 19:38:44 +0000155 if (!guc->log.vma || i915_modparams.guc_log_level < 0)
Daniele Ceraolo Spurioac58d2a2017-05-22 10:50:28 -0700156 return;
157
158 if (!guc->load_err_log)
159 guc->load_err_log = i915_gem_object_get(guc->log.vma->obj);
160
161 return;
162}
163
164static void guc_free_load_err_log(struct intel_guc *guc)
165{
166 if (guc->load_err_log)
167 i915_gem_object_put(guc->load_err_log);
168}
169
Michal Wajdeczko789a6252017-05-02 10:32:42 +0000170static int guc_enable_communication(struct intel_guc *guc)
171{
Michal Wajdeczkof8a58d62017-05-26 11:13:25 +0000172 struct drm_i915_private *dev_priv = guc_to_i915(guc);
173
Michal Wajdeczkof8a58d62017-05-26 11:13:25 +0000174 if (HAS_GUC_CT(dev_priv))
175 return intel_guc_enable_ct(guc);
176
Michal Wajdeczko789a6252017-05-02 10:32:42 +0000177 guc->send = intel_guc_send_mmio;
178 return 0;
179}
180
181static void guc_disable_communication(struct intel_guc *guc)
182{
Michal Wajdeczkof8a58d62017-05-26 11:13:25 +0000183 struct drm_i915_private *dev_priv = guc_to_i915(guc);
184
185 if (HAS_GUC_CT(dev_priv))
186 intel_guc_disable_ct(guc);
187
Michal Wajdeczko789a6252017-05-02 10:32:42 +0000188 guc->send = intel_guc_send_nop;
189}
190
Michał Winiarski3176ff42017-12-13 23:13:47 +0100191int intel_uc_init_wq(struct drm_i915_private *dev_priv)
192{
193 int ret;
194
195 if (!USES_GUC(dev_priv))
196 return 0;
197
198 ret = intel_guc_init_wq(&dev_priv->guc);
199 if (ret) {
200 DRM_ERROR("Couldn't allocate workqueues for GuC\n");
201 return ret;
202 }
203
204 return 0;
205}
206
207void intel_uc_fini_wq(struct drm_i915_private *dev_priv)
208{
209 if (!USES_GUC(dev_priv))
210 return;
211
Michał Winiarski3176ff42017-12-13 23:13:47 +0100212 intel_guc_fini_wq(&dev_priv->guc);
213}
214
Michał Winiarski61b5c152017-12-13 23:13:48 +0100215int intel_uc_init(struct drm_i915_private *dev_priv)
216{
217 struct intel_guc *guc = &dev_priv->guc;
218 int ret;
219
220 if (!USES_GUC(dev_priv))
221 return 0;
222
223 if (!HAS_GUC(dev_priv))
224 return -ENODEV;
225
226 ret = intel_guc_init(guc);
227 if (ret)
228 return ret;
229
230 if (USES_GUC_SUBMISSION(dev_priv)) {
231 /*
232 * This is stuff we need to have available at fw load time
233 * if we are planning to enable submission later
234 */
235 ret = intel_guc_submission_init(guc);
236 if (ret) {
237 intel_guc_fini(guc);
238 return ret;
239 }
240 }
241
242 return 0;
243}
244
245void intel_uc_fini(struct drm_i915_private *dev_priv)
246{
247 struct intel_guc *guc = &dev_priv->guc;
248
249 if (!USES_GUC(dev_priv))
250 return;
251
252 GEM_BUG_ON(!HAS_GUC(dev_priv));
253
254 if (USES_GUC_SUBMISSION(dev_priv))
255 intel_guc_submission_fini(guc);
256
257 intel_guc_fini(guc);
258}
259
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +0100260int intel_uc_init_hw(struct drm_i915_private *dev_priv)
261{
Michal Wajdeczko789a6252017-05-02 10:32:42 +0000262 struct intel_guc *guc = &dev_priv->guc;
Michal Wajdeczko0dfa1ce2017-12-06 13:53:16 +0000263 struct intel_huc *huc = &dev_priv->huc;
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +0100264 int ret, attempts;
265
Michal Wajdeczko93ffbe82017-12-06 13:53:12 +0000266 if (!USES_GUC(dev_priv))
Oscar Mateob8991402017-03-28 09:53:47 -0700267 return 0;
268
Michał Winiarski61b5c152017-12-13 23:13:48 +0100269 GEM_BUG_ON(!HAS_GUC(dev_priv));
Michal Wajdeczko121981f2017-12-06 13:53:15 +0000270
Michal Wajdeczko789a6252017-05-02 10:32:42 +0000271 guc_disable_communication(guc);
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +0100272 gen9_reset_guc_interrupts(dev_priv);
273
daniele.ceraolospurio@intel.com13f6c712017-04-06 17:18:52 -0700274 /* init WOPCM */
275 I915_WRITE(GUC_WOPCM_SIZE, intel_guc_wopcm_size(dev_priv));
276 I915_WRITE(DMA_GUC_WOPCM_OFFSET,
277 GUC_WOPCM_OFFSET_VALUE | HUC_LOADING_AGENT_GUC);
278
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +0100279 /* WaEnableuKernelHeaderValidFix:skl */
280 /* WaEnableGuCBootHashCheckNotSet:skl,bxt,kbl */
281 if (IS_GEN9(dev_priv))
282 attempts = 3;
283 else
284 attempts = 1;
285
286 while (attempts--) {
287 /*
288 * Always reset the GuC just before (re)loading, so
289 * that the state and timing are fairly predictable
290 */
291 ret = __intel_uc_reset_hw(dev_priv);
292 if (ret)
Michał Winiarski61b5c152017-12-13 23:13:48 +0100293 goto err_out;
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +0100294
Michal Wajdeczko0dfa1ce2017-12-06 13:53:16 +0000295 if (USES_HUC(dev_priv)) {
296 ret = intel_huc_init_hw(huc);
297 if (ret)
Michał Winiarski61b5c152017-12-13 23:13:48 +0100298 goto err_out;
Michal Wajdeczko0dfa1ce2017-12-06 13:53:16 +0000299 }
300
Michal Wajdeczko5d53be42017-10-16 14:47:11 +0000301 intel_guc_init_params(guc);
Michal Wajdeczkoe8668bb2017-10-16 14:47:14 +0000302 ret = intel_guc_fw_upload(guc);
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +0100303 if (ret == 0 || ret != -EAGAIN)
304 break;
305
306 DRM_DEBUG_DRIVER("GuC fw load failed: %d; will reset and "
307 "retry %d more time(s)\n", ret, attempts);
308 }
309
310 /* Did we succeded or run out of retries? */
311 if (ret)
Daniele Ceraolo Spurioac58d2a2017-05-22 10:50:28 -0700312 goto err_log_capture;
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +0100313
Michal Wajdeczko789a6252017-05-02 10:32:42 +0000314 ret = guc_enable_communication(guc);
315 if (ret)
Daniele Ceraolo Spurioac58d2a2017-05-22 10:50:28 -0700316 goto err_log_capture;
Michal Wajdeczko789a6252017-05-02 10:32:42 +0000317
Michal Wajdeczko0dfa1ce2017-12-06 13:53:16 +0000318 if (USES_HUC(dev_priv)) {
319 ret = intel_huc_auth(huc);
320 if (ret)
321 goto err_communication;
322 }
323
Michal Wajdeczko93ffbe82017-12-06 13:53:12 +0000324 if (USES_GUC_SUBMISSION(dev_priv)) {
Michal Wajdeczko4f044a82017-09-19 19:38:44 +0000325 if (i915_modparams.guc_log_level >= 0)
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +0100326 gen9_enable_guc_interrupts(dev_priv);
327
Sagar Arun Kambledb14d0c52017-11-16 19:02:39 +0530328 ret = intel_guc_submission_enable(guc);
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +0100329 if (ret)
Oscar Mateo3950bf32017-03-22 10:39:46 -0700330 goto err_interrupts;
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +0100331 }
332
Michal Wajdeczko93ffbe82017-12-06 13:53:12 +0000333 dev_info(dev_priv->drm.dev, "GuC firmware version %u.%u\n",
Michal Wajdeczko86ffc312017-10-16 14:47:17 +0000334 guc->fw.major_ver_found, guc->fw.minor_ver_found);
Michal Wajdeczko93ffbe82017-12-06 13:53:12 +0000335 dev_info(dev_priv->drm.dev, "GuC submission %s\n",
336 enableddisabled(USES_GUC_SUBMISSION(dev_priv)));
Michal Wajdeczko0dfa1ce2017-12-06 13:53:16 +0000337 dev_info(dev_priv->drm.dev, "HuC %s\n",
338 enableddisabled(USES_HUC(dev_priv)));
Michal Wajdeczko86ffc312017-10-16 14:47:17 +0000339
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +0100340 return 0;
341
342 /*
343 * We've failed to load the firmware :(
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +0100344 */
Oscar Mateo3950bf32017-03-22 10:39:46 -0700345err_interrupts:
346 gen9_disable_guc_interrupts(dev_priv);
Michal Wajdeczko0dfa1ce2017-12-06 13:53:16 +0000347err_communication:
348 guc_disable_communication(guc);
Daniele Ceraolo Spurioac58d2a2017-05-22 10:50:28 -0700349err_log_capture:
350 guc_capture_load_err_log(guc);
Michal Wajdeczko121981f2017-12-06 13:53:15 +0000351err_out:
352 /*
353 * Note that there is no fallback as either user explicitly asked for
354 * the GuC or driver default option was to run with the GuC enabled.
355 */
356 if (GEM_WARN_ON(ret == -EIO))
357 ret = -EINVAL;
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +0100358
Michal Wajdeczko121981f2017-12-06 13:53:15 +0000359 dev_err(dev_priv->drm.dev, "GuC initialization failed %d\n", ret);
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +0100360 return ret;
361}
362
Oscar Mateo3950bf32017-03-22 10:39:46 -0700363void intel_uc_fini_hw(struct drm_i915_private *dev_priv)
364{
Sagar Arun Kambledb14d0c52017-11-16 19:02:39 +0530365 struct intel_guc *guc = &dev_priv->guc;
366
367 guc_free_load_err_log(guc);
Michel Thierryc4a89522017-06-05 10:12:51 -0700368
Michal Wajdeczko93ffbe82017-12-06 13:53:12 +0000369 if (!USES_GUC(dev_priv))
Oscar Mateob8991402017-03-28 09:53:47 -0700370 return;
371
Michał Winiarski61b5c152017-12-13 23:13:48 +0100372 GEM_BUG_ON(!HAS_GUC(dev_priv));
373
Michal Wajdeczko93ffbe82017-12-06 13:53:12 +0000374 if (USES_GUC_SUBMISSION(dev_priv))
Sagar Arun Kambledb14d0c52017-11-16 19:02:39 +0530375 intel_guc_submission_disable(guc);
Michal Wajdeczko2f640852017-05-26 11:13:24 +0000376
Sagar Arun Kambledb14d0c52017-11-16 19:02:39 +0530377 guc_disable_communication(guc);
Michal Wajdeczko2f640852017-05-26 11:13:24 +0000378
Michał Winiarski61b5c152017-12-13 23:13:48 +0100379 if (USES_GUC_SUBMISSION(dev_priv))
Oscar Mateo3950bf32017-03-22 10:39:46 -0700380 gen9_disable_guc_interrupts(dev_priv);
Oscar Mateo3950bf32017-03-22 10:39:46 -0700381}