2 * Copyright © 2016 Intel Corporation
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:
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
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
25 #include "gt/intel_reset.h"
27 #include "intel_guc.h"
28 #include "intel_guc_ads.h"
29 #include "intel_guc_submission.h"
32 static void guc_free_load_err_log(struct intel_guc *guc);
34 /* Reset GuC providing us with fresh state for both GuC and HuC.
36 static int __intel_uc_reset_hw(struct drm_i915_private *dev_priv)
41 ret = intel_reset_guc(dev_priv);
43 DRM_ERROR("Failed to reset GuC, ret = %d\n", ret);
47 guc_status = I915_READ(GUC_STATUS);
48 WARN(!(guc_status & GS_MIA_IN_RESET),
49 "GuC status: 0x%x, MIA core expected to be in reset\n",
55 static int __get_platform_enable_guc(struct drm_i915_private *i915)
57 struct intel_uc_fw *guc_fw = &i915->guc.fw;
58 struct intel_uc_fw *huc_fw = &i915->huc.fw;
61 /* Default is to use HuC if we know GuC and HuC firmwares */
62 if (intel_uc_fw_is_selected(guc_fw) && intel_uc_fw_is_selected(huc_fw))
63 enable_guc |= ENABLE_GUC_LOAD_HUC;
65 /* Any platform specific fine-tuning can be done here */
70 static int __get_default_guc_log_level(struct drm_i915_private *i915)
74 if (!HAS_GUC(i915) || !intel_uc_is_using_guc(i915))
75 guc_log_level = GUC_LOG_LEVEL_DISABLED;
76 else if (IS_ENABLED(CONFIG_DRM_I915_DEBUG) ||
77 IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM))
78 guc_log_level = GUC_LOG_LEVEL_MAX;
80 guc_log_level = GUC_LOG_LEVEL_NON_VERBOSE;
82 /* Any platform specific fine-tuning can be done here */
88 * sanitize_options_early - sanitize uC related modparam options
89 * @i915: device private
91 * In case of "enable_guc" option this function will attempt to modify
92 * it only if it was initially set to "auto(-1)". Default value for this
93 * modparam varies between platforms and it is hardcoded in driver code.
94 * Any other modparam value is only monitored against availability of the
95 * related hardware or firmware definitions.
97 * In case of "guc_log_level" option this function will attempt to modify
98 * it only if it was initially set to "auto(-1)" or if initial value was
99 * "enable(1..4)" on platforms without the GuC. Default value for this
100 * modparam varies between platforms and is usually set to "disable(0)"
101 * unless GuC is enabled on given platform and the driver is compiled with
102 * debug config when this modparam will default to "enable(1..4)".
104 static void sanitize_options_early(struct drm_i915_private *i915)
106 struct intel_uc_fw *guc_fw = &i915->guc.fw;
107 struct intel_uc_fw *huc_fw = &i915->huc.fw;
109 /* A negative value means "use platform default" */
110 if (i915_modparams.enable_guc < 0)
111 i915_modparams.enable_guc = __get_platform_enable_guc(i915);
113 DRM_DEBUG_DRIVER("enable_guc=%d (submission:%s huc:%s)\n",
114 i915_modparams.enable_guc,
115 yesno(intel_uc_is_using_guc_submission(i915)),
116 yesno(intel_uc_is_using_huc(i915)));
118 /* Verify GuC firmware availability */
119 if (intel_uc_is_using_guc(i915) && !intel_uc_fw_is_selected(guc_fw)) {
120 DRM_WARN("Incompatible option detected: %s=%d, %s!\n",
121 "enable_guc", i915_modparams.enable_guc,
122 !HAS_GUC(i915) ? "no GuC hardware" :
126 /* Verify HuC firmware availability */
127 if (intel_uc_is_using_huc(i915) && !intel_uc_fw_is_selected(huc_fw)) {
128 DRM_WARN("Incompatible option detected: %s=%d, %s!\n",
129 "enable_guc", i915_modparams.enable_guc,
130 !HAS_HUC(i915) ? "no HuC hardware" :
134 /* XXX: GuC submission is unavailable for now */
135 if (intel_uc_is_using_guc_submission(i915)) {
136 DRM_INFO("Incompatible option detected: %s=%d, %s!\n",
137 "enable_guc", i915_modparams.enable_guc,
138 "GuC submission not supported");
139 DRM_INFO("Switching to non-GuC submission mode!\n");
140 i915_modparams.enable_guc &= ~ENABLE_GUC_SUBMISSION;
143 /* A negative value means "use platform/config default" */
144 if (i915_modparams.guc_log_level < 0)
145 i915_modparams.guc_log_level =
146 __get_default_guc_log_level(i915);
148 if (i915_modparams.guc_log_level > 0 && !intel_uc_is_using_guc(i915)) {
149 DRM_WARN("Incompatible option detected: %s=%d, %s!\n",
150 "guc_log_level", i915_modparams.guc_log_level,
151 !HAS_GUC(i915) ? "no GuC hardware" :
153 i915_modparams.guc_log_level = 0;
156 if (i915_modparams.guc_log_level > GUC_LOG_LEVEL_MAX) {
157 DRM_WARN("Incompatible option detected: %s=%d, %s!\n",
158 "guc_log_level", i915_modparams.guc_log_level,
159 "verbosity too high");
160 i915_modparams.guc_log_level = GUC_LOG_LEVEL_MAX;
163 DRM_DEBUG_DRIVER("guc_log_level=%d (enabled:%s, verbose:%s, verbosity:%d)\n",
164 i915_modparams.guc_log_level,
165 yesno(i915_modparams.guc_log_level),
166 yesno(GUC_LOG_LEVEL_IS_VERBOSE(i915_modparams.guc_log_level)),
167 GUC_LOG_LEVEL_TO_VERBOSITY(i915_modparams.guc_log_level));
169 /* Make sure that sanitization was done */
170 GEM_BUG_ON(i915_modparams.enable_guc < 0);
171 GEM_BUG_ON(i915_modparams.guc_log_level < 0);
174 void intel_uc_init_early(struct drm_i915_private *i915)
176 struct intel_guc *guc = &i915->guc;
177 struct intel_huc *huc = &i915->huc;
179 intel_guc_init_early(guc);
180 intel_huc_init_early(huc);
182 sanitize_options_early(i915);
185 void intel_uc_cleanup_early(struct drm_i915_private *i915)
187 struct intel_guc *guc = &i915->guc;
189 guc_free_load_err_log(guc);
193 * intel_uc_init_mmio - setup uC MMIO access
194 * @i915: device private
196 * Setup minimal state necessary for MMIO accesses later in the
197 * initialization sequence.
199 void intel_uc_init_mmio(struct drm_i915_private *i915)
201 intel_guc_init_send_regs(&i915->guc);
204 static void guc_capture_load_err_log(struct intel_guc *guc)
206 if (!guc->log.vma || !intel_guc_log_get_level(&guc->log))
209 if (!guc->load_err_log)
210 guc->load_err_log = i915_gem_object_get(guc->log.vma->obj);
215 static void guc_free_load_err_log(struct intel_guc *guc)
217 if (guc->load_err_log)
218 i915_gem_object_put(guc->load_err_log);
221 static void guc_reset_interrupts(struct intel_guc *guc)
223 guc->interrupts.reset(guc_to_i915(guc));
226 static void guc_enable_interrupts(struct intel_guc *guc)
228 guc->interrupts.enable(guc_to_i915(guc));
231 static void guc_disable_interrupts(struct intel_guc *guc)
233 guc->interrupts.disable(guc_to_i915(guc));
236 static int guc_enable_communication(struct intel_guc *guc)
238 guc_enable_interrupts(guc);
240 return intel_guc_ct_enable(&guc->ct);
243 static void guc_stop_communication(struct intel_guc *guc)
245 intel_guc_ct_stop(&guc->ct);
247 guc->send = intel_guc_send_nop;
248 guc->handler = intel_guc_to_host_event_handler_nop;
251 static void guc_disable_communication(struct intel_guc *guc)
253 intel_guc_ct_disable(&guc->ct);
255 guc_disable_interrupts(guc);
257 guc->send = intel_guc_send_nop;
258 guc->handler = intel_guc_to_host_event_handler_nop;
261 int intel_uc_init_misc(struct drm_i915_private *i915)
263 struct intel_guc *guc = &i915->guc;
264 struct intel_huc *huc = &i915->huc;
270 ret = intel_guc_init_misc(guc);
274 if (USES_HUC(i915)) {
275 ret = intel_huc_init_misc(huc);
283 intel_guc_fini_misc(guc);
287 void intel_uc_fini_misc(struct drm_i915_private *i915)
289 struct intel_guc *guc = &i915->guc;
290 struct intel_huc *huc = &i915->huc;
296 intel_huc_fini_misc(huc);
298 intel_guc_fini_misc(guc);
301 int intel_uc_init(struct drm_i915_private *i915)
303 struct intel_guc *guc = &i915->guc;
304 struct intel_huc *huc = &i915->huc;
313 /* XXX: GuC submission is unavailable for now */
314 GEM_BUG_ON(USES_GUC_SUBMISSION(i915));
316 ret = intel_guc_init(guc);
320 if (USES_HUC(i915)) {
321 ret = intel_huc_init(huc);
326 if (USES_GUC_SUBMISSION(i915)) {
328 * This is stuff we need to have available at fw load time
329 * if we are planning to enable submission later
331 ret = intel_guc_submission_init(guc);
346 void intel_uc_fini(struct drm_i915_private *i915)
348 struct intel_guc *guc = &i915->guc;
353 GEM_BUG_ON(!HAS_GUC(i915));
355 if (USES_GUC_SUBMISSION(i915))
356 intel_guc_submission_fini(guc);
359 intel_huc_fini(&i915->huc);
364 static void __uc_sanitize(struct drm_i915_private *i915)
366 struct intel_guc *guc = &i915->guc;
367 struct intel_huc *huc = &i915->huc;
369 GEM_BUG_ON(!HAS_GUC(i915));
371 intel_huc_sanitize(huc);
372 intel_guc_sanitize(guc);
374 __intel_uc_reset_hw(i915);
377 void intel_uc_sanitize(struct drm_i915_private *i915)
385 int intel_uc_init_hw(struct drm_i915_private *i915)
387 struct intel_guc *guc = &i915->guc;
388 struct intel_huc *huc = &i915->huc;
394 GEM_BUG_ON(!HAS_GUC(i915));
396 guc_reset_interrupts(guc);
398 /* WaEnableuKernelHeaderValidFix:skl */
399 /* WaEnableGuCBootHashCheckNotSet:skl,bxt,kbl */
407 * Always reset the GuC just before (re)loading, so
408 * that the state and timing are fairly predictable
410 ret = __intel_uc_reset_hw(i915);
414 if (USES_HUC(i915)) {
415 ret = intel_huc_fw_upload(huc);
420 intel_guc_ads_reset(guc);
421 intel_guc_init_params(guc);
422 ret = intel_guc_fw_upload(guc);
426 DRM_DEBUG_DRIVER("GuC fw load failed: %d; will reset and "
427 "retry %d more time(s)\n", ret, attempts);
430 /* Did we succeded or run out of retries? */
432 goto err_log_capture;
434 ret = guc_enable_communication(guc);
436 goto err_log_capture;
438 if (USES_HUC(i915)) {
439 ret = intel_huc_auth(huc);
441 goto err_communication;
444 ret = intel_guc_sample_forcewake(guc);
446 goto err_communication;
448 if (USES_GUC_SUBMISSION(i915)) {
449 ret = intel_guc_submission_enable(guc);
451 goto err_communication;
454 dev_info(i915->drm.dev, "GuC firmware version %u.%u\n",
455 guc->fw.major_ver_found, guc->fw.minor_ver_found);
456 dev_info(i915->drm.dev, "GuC submission %s\n",
457 enableddisabled(USES_GUC_SUBMISSION(i915)));
458 dev_info(i915->drm.dev, "HuC %s\n",
459 enableddisabled(USES_HUC(i915)));
464 * We've failed to load the firmware :(
467 guc_disable_communication(guc);
469 guc_capture_load_err_log(guc);
474 * Note that there is no fallback as either user explicitly asked for
475 * the GuC or driver default option was to run with the GuC enabled.
477 if (GEM_WARN_ON(ret == -EIO))
480 dev_err(i915->drm.dev, "GuC initialization failed %d\n", ret);
484 void intel_uc_fini_hw(struct drm_i915_private *i915)
486 struct intel_guc *guc = &i915->guc;
488 if (!intel_guc_is_loaded(guc))
491 GEM_BUG_ON(!HAS_GUC(i915));
493 if (USES_GUC_SUBMISSION(i915))
494 intel_guc_submission_disable(guc);
496 guc_disable_communication(guc);
501 * intel_uc_reset_prepare - Prepare for reset
502 * @i915: device private
504 * Preparing for full gpu reset.
506 void intel_uc_reset_prepare(struct drm_i915_private *i915)
508 struct intel_guc *guc = &i915->guc;
510 if (!intel_guc_is_loaded(guc))
513 guc_stop_communication(guc);
517 void intel_uc_runtime_suspend(struct drm_i915_private *i915)
519 struct intel_guc *guc = &i915->guc;
522 if (!intel_guc_is_loaded(guc))
525 err = intel_guc_suspend(guc);
527 DRM_DEBUG_DRIVER("Failed to suspend GuC, err=%d", err);
529 guc_disable_communication(guc);
532 void intel_uc_suspend(struct drm_i915_private *i915)
534 struct intel_guc *guc = &i915->guc;
535 intel_wakeref_t wakeref;
537 if (!intel_guc_is_loaded(guc))
540 with_intel_runtime_pm(&i915->runtime_pm, wakeref)
541 intel_uc_runtime_suspend(i915);
544 int intel_uc_resume(struct drm_i915_private *i915)
546 struct intel_guc *guc = &i915->guc;
549 if (!intel_guc_is_loaded(guc))
552 guc_enable_communication(guc);
554 err = intel_guc_resume(guc);
556 DRM_DEBUG_DRIVER("Failed to resume GuC, err=%d", err);