blob: 461047c86e0dd5abf4ea24e0d20ad79a5083df6e [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"
Michal Wajdeczkoddf79d82017-10-04 18:13:42 +000027#include "i915_drv.h"
Arkadiusz Hiler2d803c22016-11-25 18:59:35 +010028
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +010029/* Reset GuC providing us with fresh state for both GuC and HuC.
30 */
31static int __intel_uc_reset_hw(struct drm_i915_private *dev_priv)
32{
33 int ret;
34 u32 guc_status;
35
Michel Thierrycb20a3c2017-10-30 11:56:14 -070036 ret = intel_reset_guc(dev_priv);
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +010037 if (ret) {
Michel Thierrycb20a3c2017-10-30 11:56:14 -070038 DRM_ERROR("Failed to reset GuC, ret = %d\n", ret);
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +010039 return ret;
40 }
41
42 guc_status = I915_READ(GUC_STATUS);
43 WARN(!(guc_status & GS_MIA_IN_RESET),
44 "GuC status: 0x%x, MIA core expected to be in reset\n",
45 guc_status);
46
47 return ret;
48}
49
Michal Wajdeczko121981f2017-12-06 13:53:15 +000050static int __get_platform_enable_guc(struct drm_i915_private *dev_priv)
51{
52 struct intel_uc_fw *guc_fw = &dev_priv->guc.fw;
53 struct intel_uc_fw *huc_fw = &dev_priv->huc.fw;
54 int enable_guc = 0;
55
56 /* Default is to enable GuC/HuC if we know their firmwares */
57 if (intel_uc_fw_is_selected(guc_fw))
58 enable_guc |= ENABLE_GUC_SUBMISSION;
59 if (intel_uc_fw_is_selected(huc_fw))
60 enable_guc |= ENABLE_GUC_LOAD_HUC;
61
62 /* Any platform specific fine-tuning can be done here */
63
64 return enable_guc;
65}
66
67/**
68 * intel_uc_sanitize_options - sanitize uC related modparam options
69 * @dev_priv: device private
70 *
71 * In case of "enable_guc" option this function will attempt to modify
72 * it only if it was initially set to "auto(-1)". Default value for this
73 * modparam varies between platforms and it is hardcoded in driver code.
74 * Any other modparam value is only monitored against availability of the
75 * related hardware or firmware definitions.
76 */
Arkadiusz Hilerd2be9f22017-03-14 15:28:10 +010077void intel_uc_sanitize_options(struct drm_i915_private *dev_priv)
78{
Michal Wajdeczko121981f2017-12-06 13:53:15 +000079 struct intel_uc_fw *guc_fw = &dev_priv->guc.fw;
80 struct intel_uc_fw *huc_fw = &dev_priv->huc.fw;
Arkadiusz Hilerb551f612017-03-14 15:28:13 +010081
Michal Wajdeczkod4a70a12017-03-15 13:37:41 +000082 /* A negative value means "use platform default" */
Michal Wajdeczko121981f2017-12-06 13:53:15 +000083 if (i915_modparams.enable_guc < 0)
84 i915_modparams.enable_guc = __get_platform_enable_guc(dev_priv);
Michal Wajdeczkod4a70a12017-03-15 13:37:41 +000085
Michal Wajdeczko121981f2017-12-06 13:53:15 +000086 DRM_DEBUG_DRIVER("enable_guc=%d (submission:%s huc:%s)\n",
87 i915_modparams.enable_guc,
88 yesno(intel_uc_is_using_guc_submission()),
89 yesno(intel_uc_is_using_huc()));
90
91 /* Verify GuC firmware availability */
92 if (intel_uc_is_using_guc() && !intel_uc_fw_is_selected(guc_fw)) {
93 DRM_WARN("Incompatible option detected: enable_guc=%d, %s!\n",
94 i915_modparams.enable_guc,
95 !HAS_GUC(dev_priv) ? "no GuC hardware" :
96 "no GuC firmware");
Arkadiusz Hilerb551f612017-03-14 15:28:13 +010097 }
Michal Wajdeczkod4a70a12017-03-15 13:37:41 +000098
Michal Wajdeczko121981f2017-12-06 13:53:15 +000099 /* Verify HuC firmware availability */
100 if (intel_uc_is_using_huc() && !intel_uc_fw_is_selected(huc_fw)) {
101 DRM_WARN("Incompatible option detected: enable_guc=%d, %s!\n",
102 i915_modparams.enable_guc,
103 !HAS_HUC(dev_priv) ? "no HuC hardware" :
104 "no HuC firmware");
105 }
Michal Wajdeczkod4a70a12017-03-15 13:37:41 +0000106
Michal Wajdeczko121981f2017-12-06 13:53:15 +0000107 /* Make sure that sanitization was done */
108 GEM_BUG_ON(i915_modparams.enable_guc < 0);
Arkadiusz Hilerd2be9f22017-03-14 15:28:10 +0100109}
110
Michal Wajdeczko3af7a9c2017-10-04 15:33:27 +0000111void intel_uc_init_early(struct drm_i915_private *dev_priv)
112{
Michal Wajdeczko9bf384c2017-10-04 18:13:41 +0000113 intel_guc_init_early(&dev_priv->guc);
Michal Wajdeczko2fe2d4e2017-12-06 13:53:10 +0000114 intel_huc_init_early(&dev_priv->huc);
Michal Wajdeczko3af7a9c2017-10-04 15:33:27 +0000115}
116
Arkadiusz Hiler29ad6a32017-03-14 15:28:09 +0100117void intel_uc_init_fw(struct drm_i915_private *dev_priv)
118{
Michal Wajdeczkoa655aeb2017-12-06 13:53:13 +0000119 if (!USES_GUC(dev_priv))
120 return;
121
Michal Wajdeczko0dfa1ce2017-12-06 13:53:16 +0000122 if (USES_HUC(dev_priv))
123 intel_uc_fw_fetch(dev_priv, &dev_priv->huc.fw);
124
Michal Wajdeczkoa16b4312017-10-04 15:33:25 +0000125 intel_uc_fw_fetch(dev_priv, &dev_priv->guc.fw);
Arkadiusz Hiler29ad6a32017-03-14 15:28:09 +0100126}
127
Oscar Mateo3950bf32017-03-22 10:39:46 -0700128void intel_uc_fini_fw(struct drm_i915_private *dev_priv)
129{
Michal Wajdeczkoa655aeb2017-12-06 13:53:13 +0000130 if (!USES_GUC(dev_priv))
131 return;
132
Michal Wajdeczkoa16b4312017-10-04 15:33:25 +0000133 intel_uc_fw_fini(&dev_priv->guc.fw);
Michal Wajdeczko0dfa1ce2017-12-06 13:53:16 +0000134
135 if (USES_HUC(dev_priv))
136 intel_uc_fw_fini(&dev_priv->huc.fw);
Oscar Mateo3950bf32017-03-22 10:39:46 -0700137}
138
Sagar Arun Kamble1fc556f2017-10-04 15:33:24 +0000139/**
140 * intel_uc_init_mmio - setup uC MMIO access
141 *
142 * @dev_priv: device private
143 *
144 * Setup minimal state necessary for MMIO accesses later in the
145 * initialization sequence.
146 */
147void intel_uc_init_mmio(struct drm_i915_private *dev_priv)
148{
Michal Wajdeczko9bf384c2017-10-04 18:13:41 +0000149 intel_guc_init_send_regs(&dev_priv->guc);
Sagar Arun Kamble1fc556f2017-10-04 15:33:24 +0000150}
151
Daniele Ceraolo Spurioac58d2a2017-05-22 10:50:28 -0700152static void guc_capture_load_err_log(struct intel_guc *guc)
153{
Michal Wajdeczko4f044a82017-09-19 19:38:44 +0000154 if (!guc->log.vma || i915_modparams.guc_log_level < 0)
Daniele Ceraolo Spurioac58d2a2017-05-22 10:50:28 -0700155 return;
156
157 if (!guc->load_err_log)
158 guc->load_err_log = i915_gem_object_get(guc->log.vma->obj);
159
160 return;
161}
162
163static void guc_free_load_err_log(struct intel_guc *guc)
164{
165 if (guc->load_err_log)
166 i915_gem_object_put(guc->load_err_log);
167}
168
Michal Wajdeczko789a6252017-05-02 10:32:42 +0000169static int guc_enable_communication(struct intel_guc *guc)
170{
Michal Wajdeczkof8a58d62017-05-26 11:13:25 +0000171 struct drm_i915_private *dev_priv = guc_to_i915(guc);
172
Michal Wajdeczkof8a58d62017-05-26 11:13:25 +0000173 if (HAS_GUC_CT(dev_priv))
174 return intel_guc_enable_ct(guc);
175
Michal Wajdeczko789a6252017-05-02 10:32:42 +0000176 guc->send = intel_guc_send_mmio;
177 return 0;
178}
179
180static void guc_disable_communication(struct intel_guc *guc)
181{
Michal Wajdeczkof8a58d62017-05-26 11:13:25 +0000182 struct drm_i915_private *dev_priv = guc_to_i915(guc);
183
184 if (HAS_GUC_CT(dev_priv))
185 intel_guc_disable_ct(guc);
186
Michal Wajdeczko789a6252017-05-02 10:32:42 +0000187 guc->send = intel_guc_send_nop;
188}
189
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +0100190int intel_uc_init_hw(struct drm_i915_private *dev_priv)
191{
Michal Wajdeczko789a6252017-05-02 10:32:42 +0000192 struct intel_guc *guc = &dev_priv->guc;
Michal Wajdeczko0dfa1ce2017-12-06 13:53:16 +0000193 struct intel_huc *huc = &dev_priv->huc;
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +0100194 int ret, attempts;
195
Michal Wajdeczko93ffbe82017-12-06 13:53:12 +0000196 if (!USES_GUC(dev_priv))
Oscar Mateob8991402017-03-28 09:53:47 -0700197 return 0;
198
Michal Wajdeczko121981f2017-12-06 13:53:15 +0000199 if (!HAS_GUC(dev_priv)) {
200 ret = -ENODEV;
201 goto err_out;
202 }
203
Michal Wajdeczko789a6252017-05-02 10:32:42 +0000204 guc_disable_communication(guc);
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +0100205 gen9_reset_guc_interrupts(dev_priv);
206
207 /* We need to notify the guc whenever we change the GGTT */
208 i915_ggtt_enable_guc(dev_priv);
209
Michal Wajdeczko93ffbe82017-12-06 13:53:12 +0000210 if (USES_GUC_SUBMISSION(dev_priv)) {
Oscar Mateo397fce82017-03-22 10:39:52 -0700211 /*
212 * This is stuff we need to have available at fw load time
213 * if we are planning to enable submission later
214 */
Sagar Arun Kambledb14d0c52017-11-16 19:02:39 +0530215 ret = intel_guc_submission_init(guc);
Oscar Mateo397fce82017-03-22 10:39:52 -0700216 if (ret)
217 goto err_guc;
218 }
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +0100219
daniele.ceraolospurio@intel.com13f6c712017-04-06 17:18:52 -0700220 /* init WOPCM */
221 I915_WRITE(GUC_WOPCM_SIZE, intel_guc_wopcm_size(dev_priv));
222 I915_WRITE(DMA_GUC_WOPCM_OFFSET,
223 GUC_WOPCM_OFFSET_VALUE | HUC_LOADING_AGENT_GUC);
224
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +0100225 /* WaEnableuKernelHeaderValidFix:skl */
226 /* WaEnableGuCBootHashCheckNotSet:skl,bxt,kbl */
227 if (IS_GEN9(dev_priv))
228 attempts = 3;
229 else
230 attempts = 1;
231
232 while (attempts--) {
233 /*
234 * Always reset the GuC just before (re)loading, so
235 * that the state and timing are fairly predictable
236 */
237 ret = __intel_uc_reset_hw(dev_priv);
238 if (ret)
239 goto err_submission;
240
Michal Wajdeczko0dfa1ce2017-12-06 13:53:16 +0000241 if (USES_HUC(dev_priv)) {
242 ret = intel_huc_init_hw(huc);
243 if (ret)
244 goto err_submission;
245 }
246
Michal Wajdeczko5d53be42017-10-16 14:47:11 +0000247 intel_guc_init_params(guc);
Michal Wajdeczkoe8668bb2017-10-16 14:47:14 +0000248 ret = intel_guc_fw_upload(guc);
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +0100249 if (ret == 0 || ret != -EAGAIN)
250 break;
251
252 DRM_DEBUG_DRIVER("GuC fw load failed: %d; will reset and "
253 "retry %d more time(s)\n", ret, attempts);
254 }
255
256 /* Did we succeded or run out of retries? */
257 if (ret)
Daniele Ceraolo Spurioac58d2a2017-05-22 10:50:28 -0700258 goto err_log_capture;
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +0100259
Michal Wajdeczko789a6252017-05-02 10:32:42 +0000260 ret = guc_enable_communication(guc);
261 if (ret)
Daniele Ceraolo Spurioac58d2a2017-05-22 10:50:28 -0700262 goto err_log_capture;
Michal Wajdeczko789a6252017-05-02 10:32:42 +0000263
Michal Wajdeczko0dfa1ce2017-12-06 13:53:16 +0000264 if (USES_HUC(dev_priv)) {
265 ret = intel_huc_auth(huc);
266 if (ret)
267 goto err_communication;
268 }
269
Michal Wajdeczko93ffbe82017-12-06 13:53:12 +0000270 if (USES_GUC_SUBMISSION(dev_priv)) {
Michal Wajdeczko4f044a82017-09-19 19:38:44 +0000271 if (i915_modparams.guc_log_level >= 0)
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +0100272 gen9_enable_guc_interrupts(dev_priv);
273
Sagar Arun Kambledb14d0c52017-11-16 19:02:39 +0530274 ret = intel_guc_submission_enable(guc);
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +0100275 if (ret)
Oscar Mateo3950bf32017-03-22 10:39:46 -0700276 goto err_interrupts;
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +0100277 }
278
Michal Wajdeczko93ffbe82017-12-06 13:53:12 +0000279 dev_info(dev_priv->drm.dev, "GuC firmware version %u.%u\n",
Michal Wajdeczko86ffc312017-10-16 14:47:17 +0000280 guc->fw.major_ver_found, guc->fw.minor_ver_found);
Michal Wajdeczko93ffbe82017-12-06 13:53:12 +0000281 dev_info(dev_priv->drm.dev, "GuC submission %s\n",
282 enableddisabled(USES_GUC_SUBMISSION(dev_priv)));
Michal Wajdeczko0dfa1ce2017-12-06 13:53:16 +0000283 dev_info(dev_priv->drm.dev, "HuC %s\n",
284 enableddisabled(USES_HUC(dev_priv)));
Michal Wajdeczko86ffc312017-10-16 14:47:17 +0000285
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +0100286 return 0;
287
288 /*
289 * We've failed to load the firmware :(
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +0100290 */
Oscar Mateo3950bf32017-03-22 10:39:46 -0700291err_interrupts:
292 gen9_disable_guc_interrupts(dev_priv);
Michal Wajdeczko0dfa1ce2017-12-06 13:53:16 +0000293err_communication:
294 guc_disable_communication(guc);
Daniele Ceraolo Spurioac58d2a2017-05-22 10:50:28 -0700295err_log_capture:
296 guc_capture_load_err_log(guc);
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +0100297err_submission:
Michal Wajdeczko93ffbe82017-12-06 13:53:12 +0000298 if (USES_GUC_SUBMISSION(dev_priv))
Sagar Arun Kambledb14d0c52017-11-16 19:02:39 +0530299 intel_guc_submission_fini(guc);
Oscar Mateo3950bf32017-03-22 10:39:46 -0700300err_guc:
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +0100301 i915_ggtt_disable_guc(dev_priv);
Michal Wajdeczko121981f2017-12-06 13:53:15 +0000302err_out:
303 /*
304 * Note that there is no fallback as either user explicitly asked for
305 * the GuC or driver default option was to run with the GuC enabled.
306 */
307 if (GEM_WARN_ON(ret == -EIO))
308 ret = -EINVAL;
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +0100309
Michal Wajdeczko121981f2017-12-06 13:53:15 +0000310 dev_err(dev_priv->drm.dev, "GuC initialization failed %d\n", ret);
Arkadiusz Hiler6cd5a722017-03-14 15:28:11 +0100311 return ret;
312}
313
Oscar Mateo3950bf32017-03-22 10:39:46 -0700314void intel_uc_fini_hw(struct drm_i915_private *dev_priv)
315{
Sagar Arun Kambledb14d0c52017-11-16 19:02:39 +0530316 struct intel_guc *guc = &dev_priv->guc;
317
318 guc_free_load_err_log(guc);
Michel Thierryc4a89522017-06-05 10:12:51 -0700319
Michal Wajdeczko93ffbe82017-12-06 13:53:12 +0000320 if (!USES_GUC(dev_priv))
Oscar Mateob8991402017-03-28 09:53:47 -0700321 return;
322
Michal Wajdeczko93ffbe82017-12-06 13:53:12 +0000323 if (USES_GUC_SUBMISSION(dev_priv))
Sagar Arun Kambledb14d0c52017-11-16 19:02:39 +0530324 intel_guc_submission_disable(guc);
Michal Wajdeczko2f640852017-05-26 11:13:24 +0000325
Sagar Arun Kambledb14d0c52017-11-16 19:02:39 +0530326 guc_disable_communication(guc);
Michal Wajdeczko2f640852017-05-26 11:13:24 +0000327
Michal Wajdeczko93ffbe82017-12-06 13:53:12 +0000328 if (USES_GUC_SUBMISSION(dev_priv)) {
Oscar Mateo3950bf32017-03-22 10:39:46 -0700329 gen9_disable_guc_interrupts(dev_priv);
Sagar Arun Kambledb14d0c52017-11-16 19:02:39 +0530330 intel_guc_submission_fini(guc);
Oscar Mateo3950bf32017-03-22 10:39:46 -0700331 }
Michal Wajdeczko2f640852017-05-26 11:13:24 +0000332
Oscar Mateo3950bf32017-03-22 10:39:46 -0700333 i915_ggtt_disable_guc(dev_priv);
334}