xref: /dflybsd-src/sys/dev/drm/i915/intel_uc.c (revision 3f2dd94a569761201b5b0a18b2f697f97fe1b9dc)
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