1a85cb24fSFrançois Tigeot /*
2a85cb24fSFrançois Tigeot * Copyright © 2016 Intel Corporation
3a85cb24fSFrançois Tigeot *
4a85cb24fSFrançois Tigeot * Permission is hereby granted, free of charge, to any person obtaining a
5a85cb24fSFrançois Tigeot * copy of this software and associated documentation files (the "Software"),
6a85cb24fSFrançois Tigeot * to deal in the Software without restriction, including without limitation
7a85cb24fSFrançois Tigeot * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8a85cb24fSFrançois Tigeot * and/or sell copies of the Software, and to permit persons to whom the
9a85cb24fSFrançois Tigeot * Software is furnished to do so, subject to the following conditions:
10a85cb24fSFrançois Tigeot *
11a85cb24fSFrançois Tigeot * The above copyright notice and this permission notice (including the next
12a85cb24fSFrançois Tigeot * paragraph) shall be included in all copies or substantial portions of the
13a85cb24fSFrançois Tigeot * Software.
14a85cb24fSFrançois Tigeot *
15a85cb24fSFrançois Tigeot * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16a85cb24fSFrançois Tigeot * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17a85cb24fSFrançois Tigeot * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18a85cb24fSFrançois Tigeot * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19a85cb24fSFrançois Tigeot * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20a85cb24fSFrançois Tigeot * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21a85cb24fSFrançois Tigeot * IN THE SOFTWARE.
22a85cb24fSFrançois Tigeot *
23a85cb24fSFrançois Tigeot */
24a85cb24fSFrançois Tigeot
25a85cb24fSFrançois Tigeot #include "intel_uc.h"
26*3f2dd94aSFrançois Tigeot #include "i915_drv.h"
27*3f2dd94aSFrançois Tigeot #include "i915_guc_submission.h"
28a85cb24fSFrançois Tigeot
29a85cb24fSFrançois Tigeot /* Reset GuC providing us with fresh state for both GuC and HuC.
30a85cb24fSFrançois Tigeot */
__intel_uc_reset_hw(struct drm_i915_private * dev_priv)31a85cb24fSFrançois Tigeot static int __intel_uc_reset_hw(struct drm_i915_private *dev_priv)
32a85cb24fSFrançois Tigeot {
33a85cb24fSFrançois Tigeot int ret;
34a85cb24fSFrançois Tigeot u32 guc_status;
35a85cb24fSFrançois Tigeot
36a85cb24fSFrançois Tigeot ret = intel_guc_reset(dev_priv);
37a85cb24fSFrançois Tigeot if (ret) {
38a85cb24fSFrançois Tigeot DRM_ERROR("GuC reset failed, ret = %d\n", ret);
39a85cb24fSFrançois Tigeot return ret;
40a85cb24fSFrançois Tigeot }
41a85cb24fSFrançois Tigeot
42a85cb24fSFrançois Tigeot guc_status = I915_READ(GUC_STATUS);
43a85cb24fSFrançois Tigeot WARN(!(guc_status & GS_MIA_IN_RESET),
44a85cb24fSFrançois Tigeot "GuC status: 0x%x, MIA core expected to be in reset\n",
45a85cb24fSFrançois Tigeot guc_status);
46a85cb24fSFrançois Tigeot
47a85cb24fSFrançois Tigeot return ret;
48a85cb24fSFrançois Tigeot }
49a85cb24fSFrançois Tigeot
intel_uc_sanitize_options(struct drm_i915_private * dev_priv)50a85cb24fSFrançois Tigeot void intel_uc_sanitize_options(struct drm_i915_private *dev_priv)
51a85cb24fSFrançois Tigeot {
52a85cb24fSFrançois Tigeot if (!HAS_GUC(dev_priv)) {
53*3f2dd94aSFrançois Tigeot if (i915_modparams.enable_guc_loading > 0 ||
54*3f2dd94aSFrançois Tigeot i915_modparams.enable_guc_submission > 0)
55a85cb24fSFrançois Tigeot DRM_INFO("Ignoring GuC options, no hardware\n");
56a85cb24fSFrançois Tigeot
57*3f2dd94aSFrançois Tigeot i915_modparams.enable_guc_loading = 0;
58*3f2dd94aSFrançois Tigeot i915_modparams.enable_guc_submission = 0;
59a85cb24fSFrançois Tigeot return;
60a85cb24fSFrançois Tigeot }
61a85cb24fSFrançois Tigeot
62a85cb24fSFrançois Tigeot /* A negative value means "use platform default" */
63*3f2dd94aSFrançois Tigeot if (i915_modparams.enable_guc_loading < 0)
64*3f2dd94aSFrançois Tigeot i915_modparams.enable_guc_loading = HAS_GUC_UCODE(dev_priv);
65a85cb24fSFrançois Tigeot
66a85cb24fSFrançois Tigeot /* Verify firmware version */
67*3f2dd94aSFrançois Tigeot if (i915_modparams.enable_guc_loading) {
68a85cb24fSFrançois Tigeot if (HAS_HUC_UCODE(dev_priv))
69a85cb24fSFrançois Tigeot intel_huc_select_fw(&dev_priv->huc);
70a85cb24fSFrançois Tigeot
71*3f2dd94aSFrançois Tigeot if (intel_guc_fw_select(&dev_priv->guc))
72*3f2dd94aSFrançois Tigeot i915_modparams.enable_guc_loading = 0;
73a85cb24fSFrançois Tigeot }
74a85cb24fSFrançois Tigeot
75a85cb24fSFrançois Tigeot /* Can't enable guc submission without guc loaded */
76*3f2dd94aSFrançois Tigeot if (!i915_modparams.enable_guc_loading)
77*3f2dd94aSFrançois Tigeot i915_modparams.enable_guc_submission = 0;
78a85cb24fSFrançois Tigeot
79a85cb24fSFrançois Tigeot /* A negative value means "use platform default" */
80*3f2dd94aSFrançois Tigeot if (i915_modparams.enable_guc_submission < 0)
81*3f2dd94aSFrançois Tigeot i915_modparams.enable_guc_submission = HAS_GUC_SCHED(dev_priv);
82a85cb24fSFrançois Tigeot }
83a85cb24fSFrançois Tigeot
intel_uc_init_early(struct drm_i915_private * dev_priv)84a85cb24fSFrançois Tigeot void intel_uc_init_early(struct drm_i915_private *dev_priv)
85a85cb24fSFrançois Tigeot {
86*3f2dd94aSFrançois Tigeot intel_guc_init_early(&dev_priv->guc);
87a85cb24fSFrançois Tigeot }
88a85cb24fSFrançois Tigeot
intel_uc_init_fw(struct drm_i915_private * dev_priv)89a85cb24fSFrançois Tigeot void intel_uc_init_fw(struct drm_i915_private *dev_priv)
90a85cb24fSFrançois Tigeot {
91*3f2dd94aSFrançois Tigeot intel_uc_fw_fetch(dev_priv, &dev_priv->huc.fw);
92*3f2dd94aSFrançois Tigeot intel_uc_fw_fetch(dev_priv, &dev_priv->guc.fw);
93a85cb24fSFrançois Tigeot }
94a85cb24fSFrançois Tigeot
intel_uc_fini_fw(struct drm_i915_private * dev_priv)95a85cb24fSFrançois Tigeot void intel_uc_fini_fw(struct drm_i915_private *dev_priv)
96a85cb24fSFrançois Tigeot {
97*3f2dd94aSFrançois Tigeot intel_uc_fw_fini(&dev_priv->guc.fw);
98*3f2dd94aSFrançois Tigeot intel_uc_fw_fini(&dev_priv->huc.fw);
99*3f2dd94aSFrançois Tigeot }
100*3f2dd94aSFrançois Tigeot
101*3f2dd94aSFrançois Tigeot /**
102*3f2dd94aSFrançois Tigeot * intel_uc_init_mmio - setup uC MMIO access
103*3f2dd94aSFrançois Tigeot *
104*3f2dd94aSFrançois Tigeot * @dev_priv: device private
105*3f2dd94aSFrançois Tigeot *
106*3f2dd94aSFrançois Tigeot * Setup minimal state necessary for MMIO accesses later in the
107*3f2dd94aSFrançois Tigeot * initialization sequence.
108*3f2dd94aSFrançois Tigeot */
intel_uc_init_mmio(struct drm_i915_private * dev_priv)109*3f2dd94aSFrançois Tigeot void intel_uc_init_mmio(struct drm_i915_private *dev_priv)
110*3f2dd94aSFrançois Tigeot {
111*3f2dd94aSFrançois Tigeot intel_guc_init_send_regs(&dev_priv->guc);
112*3f2dd94aSFrançois Tigeot }
113*3f2dd94aSFrançois Tigeot
guc_capture_load_err_log(struct intel_guc * guc)114*3f2dd94aSFrançois Tigeot static void guc_capture_load_err_log(struct intel_guc *guc)
115*3f2dd94aSFrançois Tigeot {
116*3f2dd94aSFrançois Tigeot if (!guc->log.vma || i915_modparams.guc_log_level < 0)
117*3f2dd94aSFrançois Tigeot return;
118*3f2dd94aSFrançois Tigeot
119*3f2dd94aSFrançois Tigeot if (!guc->load_err_log)
120*3f2dd94aSFrançois Tigeot guc->load_err_log = i915_gem_object_get(guc->log.vma->obj);
121*3f2dd94aSFrançois Tigeot
122*3f2dd94aSFrançois Tigeot return;
123*3f2dd94aSFrançois Tigeot }
124*3f2dd94aSFrançois Tigeot
guc_free_load_err_log(struct intel_guc * guc)125*3f2dd94aSFrançois Tigeot static void guc_free_load_err_log(struct intel_guc *guc)
126*3f2dd94aSFrançois Tigeot {
127*3f2dd94aSFrançois Tigeot if (guc->load_err_log)
128*3f2dd94aSFrançois Tigeot i915_gem_object_put(guc->load_err_log);
129*3f2dd94aSFrançois Tigeot }
130*3f2dd94aSFrançois Tigeot
guc_enable_communication(struct intel_guc * guc)131*3f2dd94aSFrançois Tigeot static int guc_enable_communication(struct intel_guc *guc)
132*3f2dd94aSFrançois Tigeot {
133*3f2dd94aSFrançois Tigeot struct drm_i915_private *dev_priv = guc_to_i915(guc);
134*3f2dd94aSFrançois Tigeot
135*3f2dd94aSFrançois Tigeot if (HAS_GUC_CT(dev_priv))
136*3f2dd94aSFrançois Tigeot return intel_guc_enable_ct(guc);
137*3f2dd94aSFrançois Tigeot
138*3f2dd94aSFrançois Tigeot guc->send = intel_guc_send_mmio;
139*3f2dd94aSFrançois Tigeot return 0;
140*3f2dd94aSFrançois Tigeot }
141*3f2dd94aSFrançois Tigeot
guc_disable_communication(struct intel_guc * guc)142*3f2dd94aSFrançois Tigeot static void guc_disable_communication(struct intel_guc *guc)
143*3f2dd94aSFrançois Tigeot {
144*3f2dd94aSFrançois Tigeot struct drm_i915_private *dev_priv = guc_to_i915(guc);
145*3f2dd94aSFrançois Tigeot
146*3f2dd94aSFrançois Tigeot if (HAS_GUC_CT(dev_priv))
147*3f2dd94aSFrançois Tigeot intel_guc_disable_ct(guc);
148*3f2dd94aSFrançois Tigeot
149*3f2dd94aSFrançois Tigeot guc->send = intel_guc_send_nop;
150a85cb24fSFrançois Tigeot }
151a85cb24fSFrançois Tigeot
intel_uc_init_hw(struct drm_i915_private * dev_priv)152a85cb24fSFrançois Tigeot int intel_uc_init_hw(struct drm_i915_private *dev_priv)
153a85cb24fSFrançois Tigeot {
154*3f2dd94aSFrançois Tigeot struct intel_guc *guc = &dev_priv->guc;
155a85cb24fSFrançois Tigeot int ret, attempts;
156a85cb24fSFrançois Tigeot
157*3f2dd94aSFrançois Tigeot if (!i915_modparams.enable_guc_loading)
158a85cb24fSFrançois Tigeot return 0;
159a85cb24fSFrançois Tigeot
160*3f2dd94aSFrançois Tigeot guc_disable_communication(guc);
161a85cb24fSFrançois Tigeot gen9_reset_guc_interrupts(dev_priv);
162a85cb24fSFrançois Tigeot
163a85cb24fSFrançois Tigeot /* We need to notify the guc whenever we change the GGTT */
164a85cb24fSFrançois Tigeot i915_ggtt_enable_guc(dev_priv);
165a85cb24fSFrançois Tigeot
166*3f2dd94aSFrançois Tigeot if (i915_modparams.enable_guc_submission) {
167a85cb24fSFrançois Tigeot /*
168a85cb24fSFrançois Tigeot * This is stuff we need to have available at fw load time
169a85cb24fSFrançois Tigeot * if we are planning to enable submission later
170a85cb24fSFrançois Tigeot */
171a85cb24fSFrançois Tigeot ret = i915_guc_submission_init(dev_priv);
172a85cb24fSFrançois Tigeot if (ret)
173a85cb24fSFrançois Tigeot goto err_guc;
174a85cb24fSFrançois Tigeot }
175a85cb24fSFrançois Tigeot
176*3f2dd94aSFrançois Tigeot /* init WOPCM */
177*3f2dd94aSFrançois Tigeot I915_WRITE(GUC_WOPCM_SIZE, intel_guc_wopcm_size(dev_priv));
178*3f2dd94aSFrançois Tigeot I915_WRITE(DMA_GUC_WOPCM_OFFSET,
179*3f2dd94aSFrançois Tigeot GUC_WOPCM_OFFSET_VALUE | HUC_LOADING_AGENT_GUC);
180*3f2dd94aSFrançois Tigeot
181a85cb24fSFrançois Tigeot /* WaEnableuKernelHeaderValidFix:skl */
182a85cb24fSFrançois Tigeot /* WaEnableGuCBootHashCheckNotSet:skl,bxt,kbl */
183a85cb24fSFrançois Tigeot if (IS_GEN9(dev_priv))
184a85cb24fSFrançois Tigeot attempts = 3;
185a85cb24fSFrançois Tigeot else
186a85cb24fSFrançois Tigeot attempts = 1;
187a85cb24fSFrançois Tigeot
188a85cb24fSFrançois Tigeot while (attempts--) {
189a85cb24fSFrançois Tigeot /*
190a85cb24fSFrançois Tigeot * Always reset the GuC just before (re)loading, so
191a85cb24fSFrançois Tigeot * that the state and timing are fairly predictable
192a85cb24fSFrançois Tigeot */
193a85cb24fSFrançois Tigeot ret = __intel_uc_reset_hw(dev_priv);
194a85cb24fSFrançois Tigeot if (ret)
195a85cb24fSFrançois Tigeot goto err_submission;
196a85cb24fSFrançois Tigeot
197a85cb24fSFrançois Tigeot intel_huc_init_hw(&dev_priv->huc);
198*3f2dd94aSFrançois Tigeot intel_guc_init_params(guc);
199*3f2dd94aSFrançois Tigeot ret = intel_guc_fw_upload(guc);
200a85cb24fSFrançois Tigeot if (ret == 0 || ret != -EAGAIN)
201a85cb24fSFrançois Tigeot break;
202a85cb24fSFrançois Tigeot
203a85cb24fSFrançois Tigeot DRM_DEBUG_DRIVER("GuC fw load failed: %d; will reset and "
204a85cb24fSFrançois Tigeot "retry %d more time(s)\n", ret, attempts);
205a85cb24fSFrançois Tigeot }
206a85cb24fSFrançois Tigeot
207a85cb24fSFrançois Tigeot /* Did we succeded or run out of retries? */
208a85cb24fSFrançois Tigeot if (ret)
209*3f2dd94aSFrançois Tigeot goto err_log_capture;
210a85cb24fSFrançois Tigeot
211*3f2dd94aSFrançois Tigeot ret = guc_enable_communication(guc);
212*3f2dd94aSFrançois Tigeot if (ret)
213*3f2dd94aSFrançois Tigeot goto err_log_capture;
214*3f2dd94aSFrançois Tigeot
215*3f2dd94aSFrançois Tigeot intel_huc_auth(&dev_priv->huc);
216*3f2dd94aSFrançois Tigeot if (i915_modparams.enable_guc_submission) {
217*3f2dd94aSFrançois Tigeot if (i915_modparams.guc_log_level >= 0)
218a85cb24fSFrançois Tigeot gen9_enable_guc_interrupts(dev_priv);
219a85cb24fSFrançois Tigeot
220a85cb24fSFrançois Tigeot ret = i915_guc_submission_enable(dev_priv);
221a85cb24fSFrançois Tigeot if (ret)
222a85cb24fSFrançois Tigeot goto err_interrupts;
223a85cb24fSFrançois Tigeot }
224a85cb24fSFrançois Tigeot
225*3f2dd94aSFrançois Tigeot dev_info(dev_priv->drm.dev, "GuC %s (firmware %s [version %u.%u])\n",
226*3f2dd94aSFrançois Tigeot i915_modparams.enable_guc_submission ? "submission enabled" :
227*3f2dd94aSFrançois Tigeot "loaded",
228*3f2dd94aSFrançois Tigeot guc->fw.path,
229*3f2dd94aSFrançois Tigeot guc->fw.major_ver_found, guc->fw.minor_ver_found);
230*3f2dd94aSFrançois Tigeot
231a85cb24fSFrançois Tigeot return 0;
232a85cb24fSFrançois Tigeot
233a85cb24fSFrançois Tigeot /*
234a85cb24fSFrançois Tigeot * We've failed to load the firmware :(
235a85cb24fSFrançois Tigeot *
236a85cb24fSFrançois Tigeot * Decide whether to disable GuC submission and fall back to
237a85cb24fSFrançois Tigeot * execlist mode, and whether to hide the error by returning
238a85cb24fSFrançois Tigeot * zero or to return -EIO, which the caller will treat as a
239a85cb24fSFrançois Tigeot * nonfatal error (i.e. it doesn't prevent driver load, but
240a85cb24fSFrançois Tigeot * marks the GPU as wedged until reset).
241a85cb24fSFrançois Tigeot */
242a85cb24fSFrançois Tigeot err_interrupts:
243*3f2dd94aSFrançois Tigeot guc_disable_communication(guc);
244a85cb24fSFrançois Tigeot gen9_disable_guc_interrupts(dev_priv);
245*3f2dd94aSFrançois Tigeot err_log_capture:
246*3f2dd94aSFrançois Tigeot guc_capture_load_err_log(guc);
247a85cb24fSFrançois Tigeot err_submission:
248*3f2dd94aSFrançois Tigeot if (i915_modparams.enable_guc_submission)
249a85cb24fSFrançois Tigeot i915_guc_submission_fini(dev_priv);
250a85cb24fSFrançois Tigeot err_guc:
251a85cb24fSFrançois Tigeot i915_ggtt_disable_guc(dev_priv);
252a85cb24fSFrançois Tigeot
253*3f2dd94aSFrançois Tigeot if (i915_modparams.enable_guc_loading > 1 ||
254*3f2dd94aSFrançois Tigeot i915_modparams.enable_guc_submission > 1) {
255*3f2dd94aSFrançois Tigeot DRM_ERROR("GuC init failed. Firmware loading disabled.\n");
256a85cb24fSFrançois Tigeot ret = -EIO;
257*3f2dd94aSFrançois Tigeot } else {
258*3f2dd94aSFrançois Tigeot DRM_NOTE("GuC init failed. Firmware loading disabled.\n");
259a85cb24fSFrançois Tigeot ret = 0;
260*3f2dd94aSFrançois Tigeot }
261a85cb24fSFrançois Tigeot
262*3f2dd94aSFrançois Tigeot if (i915_modparams.enable_guc_submission) {
263*3f2dd94aSFrançois Tigeot i915_modparams.enable_guc_submission = 0;
264a85cb24fSFrançois Tigeot DRM_NOTE("Falling back from GuC submission to execlist mode\n");
265a85cb24fSFrançois Tigeot }
266a85cb24fSFrançois Tigeot
267*3f2dd94aSFrançois Tigeot i915_modparams.enable_guc_loading = 0;
268*3f2dd94aSFrançois Tigeot
269a85cb24fSFrançois Tigeot return ret;
270a85cb24fSFrançois Tigeot }
271a85cb24fSFrançois Tigeot
intel_uc_fini_hw(struct drm_i915_private * dev_priv)272a85cb24fSFrançois Tigeot void intel_uc_fini_hw(struct drm_i915_private *dev_priv)
273a85cb24fSFrançois Tigeot {
274*3f2dd94aSFrançois Tigeot guc_free_load_err_log(&dev_priv->guc);
275*3f2dd94aSFrançois Tigeot
276*3f2dd94aSFrançois Tigeot if (!i915_modparams.enable_guc_loading)
277a85cb24fSFrançois Tigeot return;
278a85cb24fSFrançois Tigeot
279*3f2dd94aSFrançois Tigeot if (i915_modparams.enable_guc_submission)
280a85cb24fSFrançois Tigeot i915_guc_submission_disable(dev_priv);
281*3f2dd94aSFrançois Tigeot
282*3f2dd94aSFrançois Tigeot guc_disable_communication(&dev_priv->guc);
283*3f2dd94aSFrançois Tigeot
284*3f2dd94aSFrançois Tigeot if (i915_modparams.enable_guc_submission) {
285a85cb24fSFrançois Tigeot gen9_disable_guc_interrupts(dev_priv);
286a85cb24fSFrançois Tigeot i915_guc_submission_fini(dev_priv);
287a85cb24fSFrançois Tigeot }
288*3f2dd94aSFrançois Tigeot
289a85cb24fSFrançois Tigeot i915_ggtt_disable_guc(dev_priv);
290a85cb24fSFrançois Tigeot }
291