13ea58029SMichal Wajdeczko // SPDX-License-Identifier: MIT
20f261b24SDaniele Ceraolo Spurio /*
33ea58029SMichal Wajdeczko * Copyright © 2016-2019 Intel Corporation
40f261b24SDaniele Ceraolo Spurio */
50f261b24SDaniele Ceraolo Spurio
601fabda8SLucas De Marchi #include <linux/string_helpers.h>
701fabda8SLucas De Marchi
8ca7b2c1bSDaniele Ceraolo Spurio #include "gt/intel_gt.h"
92f8c06cbSMichal Wajdeczko #include "gt/intel_gt_print.h"
100f261b24SDaniele Ceraolo Spurio #include "gt/intel_reset.h"
1115bd4a67SDaniele Ceraolo Spurio #include "intel_gsc_fw.h"
12242c4b91SDaniele Ceraolo Spurio #include "intel_gsc_uc.h"
130f261b24SDaniele Ceraolo Spurio #include "intel_guc.h"
140f261b24SDaniele Ceraolo Spurio #include "intel_guc_ads.h"
152f8c06cbSMichal Wajdeczko #include "intel_guc_print.h"
160f261b24SDaniele Ceraolo Spurio #include "intel_guc_submission.h"
171c40d40fSVinay Belgaumkar #include "gt/intel_rps.h"
18ca7b2c1bSDaniele Ceraolo Spurio #include "intel_uc.h"
19ca7b2c1bSDaniele Ceraolo Spurio
200f261b24SDaniele Ceraolo Spurio #include "i915_drv.h"
211b44019aSAshutosh Dixit #include "i915_hwmon.h"
220f261b24SDaniele Ceraolo Spurio
236fbeda0bSMichal Wajdeczko static const struct intel_uc_ops uc_ops_off;
246fbeda0bSMichal Wajdeczko static const struct intel_uc_ops uc_ops_on;
256fbeda0bSMichal Wajdeczko
uc_expand_default_options(struct intel_uc * uc)261e58215fSJohn Harrison static void uc_expand_default_options(struct intel_uc *uc)
271e58215fSJohn Harrison {
281e58215fSJohn Harrison struct drm_i915_private *i915 = uc_to_gt(uc)->i915;
291e58215fSJohn Harrison
301e58215fSJohn Harrison if (i915->params.enable_guc != -1)
311e58215fSJohn Harrison return;
321e58215fSJohn Harrison
331e58215fSJohn Harrison /* Don't enable GuC/HuC on pre-Gen12 */
34c816723bSLucas De Marchi if (GRAPHICS_VER(i915) < 12) {
351e58215fSJohn Harrison i915->params.enable_guc = 0;
361e58215fSJohn Harrison return;
371e58215fSJohn Harrison }
381e58215fSJohn Harrison
391e58215fSJohn Harrison /* Don't enable GuC/HuC on older Gen12 platforms */
401e58215fSJohn Harrison if (IS_TIGERLAKE(i915) || IS_ROCKETLAKE(i915)) {
411e58215fSJohn Harrison i915->params.enable_guc = 0;
421e58215fSJohn Harrison return;
431e58215fSJohn Harrison }
441e58215fSJohn Harrison
45e754dccbSDaniele Ceraolo Spurio /* Intermediate platforms are HuC authentication only */
46*2aa01e4dSDnyaneshwar Bhadane if (IS_ALDERLAKE_S(i915) && !IS_RAPTORLAKE_S(i915)) {
471e58215fSJohn Harrison i915->params.enable_guc = ENABLE_GUC_LOAD_HUC;
48e754dccbSDaniele Ceraolo Spurio return;
49e754dccbSDaniele Ceraolo Spurio }
50e754dccbSDaniele Ceraolo Spurio
51e754dccbSDaniele Ceraolo Spurio /* Default: enable HuC authentication and GuC submission */
52e754dccbSDaniele Ceraolo Spurio i915->params.enable_guc = ENABLE_GUC_LOAD_HUC | ENABLE_GUC_SUBMISSION;
53a4f263f4SDaniele Ceraolo Spurio
54a4f263f4SDaniele Ceraolo Spurio /* XEHPSDV and PVC do not use HuC */
55a4f263f4SDaniele Ceraolo Spurio if (IS_XEHPSDV(i915) || IS_PONTEVECCHIO(i915))
56a4f263f4SDaniele Ceraolo Spurio i915->params.enable_guc &= ~ENABLE_GUC_LOAD_HUC;
571e58215fSJohn Harrison }
581e58215fSJohn Harrison
590f261b24SDaniele Ceraolo Spurio /* Reset GuC providing us with fresh state for both GuC and HuC.
600f261b24SDaniele Ceraolo Spurio */
__intel_uc_reset_hw(struct intel_uc * uc)61ca7b2c1bSDaniele Ceraolo Spurio static int __intel_uc_reset_hw(struct intel_uc *uc)
620f261b24SDaniele Ceraolo Spurio {
633fcba881SDaniele Ceraolo Spurio struct intel_gt *gt = uc_to_gt(uc);
640f261b24SDaniele Ceraolo Spurio int ret;
650f261b24SDaniele Ceraolo Spurio u32 guc_status;
660f261b24SDaniele Ceraolo Spurio
67dd6e38dfSJanusz Krzysztofik ret = i915_inject_probe_error(gt->i915, -ENXIO);
685d1ef2b4SMichal Wajdeczko if (ret)
695d1ef2b4SMichal Wajdeczko return ret;
705d1ef2b4SMichal Wajdeczko
713fcba881SDaniele Ceraolo Spurio ret = intel_reset_guc(gt);
720f261b24SDaniele Ceraolo Spurio if (ret) {
732f8c06cbSMichal Wajdeczko gt_err(gt, "Failed to reset GuC, ret = %d\n", ret);
740f261b24SDaniele Ceraolo Spurio return ret;
750f261b24SDaniele Ceraolo Spurio }
760f261b24SDaniele Ceraolo Spurio
773fcba881SDaniele Ceraolo Spurio guc_status = intel_uncore_read(gt->uncore, GUC_STATUS);
782f8c06cbSMichal Wajdeczko gt_WARN(gt, !(guc_status & GS_MIA_IN_RESET),
790f261b24SDaniele Ceraolo Spurio "GuC status: 0x%x, MIA core expected to be in reset\n",
800f261b24SDaniele Ceraolo Spurio guc_status);
810f261b24SDaniele Ceraolo Spurio
820f261b24SDaniele Ceraolo Spurio return ret;
830f261b24SDaniele Ceraolo Spurio }
840f261b24SDaniele Ceraolo Spurio
__confirm_options(struct intel_uc * uc)8501158da7SMichal Wajdeczko static void __confirm_options(struct intel_uc *uc)
860f261b24SDaniele Ceraolo Spurio {
874fd4fde8SJohn Harrison struct intel_gt *gt = uc_to_gt(uc);
884fd4fde8SJohn Harrison struct drm_i915_private *i915 = gt->i915;
8912be4a4cSMichal Wajdeczko
904fd4fde8SJohn Harrison gt_dbg(gt, "enable_guc=%d (guc:%s submission:%s huc:%s slpc:%s)\n",
918a25c4beSJani Nikula i915->params.enable_guc,
9201fabda8SLucas De Marchi str_yes_no(intel_uc_wants_guc(uc)),
9301fabda8SLucas De Marchi str_yes_no(intel_uc_wants_guc_submission(uc)),
9401fabda8SLucas De Marchi str_yes_no(intel_uc_wants_huc(uc)),
9501fabda8SLucas De Marchi str_yes_no(intel_uc_wants_guc_slpc(uc)));
960f261b24SDaniele Ceraolo Spurio
978a25c4beSJani Nikula if (i915->params.enable_guc == 0) {
98bfe5a40aSDaniele Ceraolo Spurio GEM_BUG_ON(intel_uc_wants_guc(uc));
99202c98e7SDaniele Ceraolo Spurio GEM_BUG_ON(intel_uc_wants_guc_submission(uc));
100bfe5a40aSDaniele Ceraolo Spurio GEM_BUG_ON(intel_uc_wants_huc(uc));
101dff0fc49SVinay Belgaumkar GEM_BUG_ON(intel_uc_wants_guc_slpc(uc));
10201158da7SMichal Wajdeczko return;
1030f261b24SDaniele Ceraolo Spurio }
1040f261b24SDaniele Ceraolo Spurio
10501158da7SMichal Wajdeczko if (!intel_uc_supports_guc(uc))
1064fd4fde8SJohn Harrison gt_info(gt, "Incompatible option enable_guc=%d - %s\n",
1078a25c4beSJani Nikula i915->params.enable_guc, "GuC is not supported!");
1080f261b24SDaniele Ceraolo Spurio
1098a25c4beSJani Nikula if (i915->params.enable_guc & ENABLE_GUC_LOAD_HUC &&
11001158da7SMichal Wajdeczko !intel_uc_supports_huc(uc))
1114fd4fde8SJohn Harrison gt_info(gt, "Incompatible option enable_guc=%d - %s\n",
1128a25c4beSJani Nikula i915->params.enable_guc, "HuC is not supported!");
1130f261b24SDaniele Ceraolo Spurio
1148a25c4beSJani Nikula if (i915->params.enable_guc & ENABLE_GUC_SUBMISSION &&
11501158da7SMichal Wajdeczko !intel_uc_supports_guc_submission(uc))
1164fd4fde8SJohn Harrison gt_info(gt, "Incompatible option enable_guc=%d - %s\n",
1178a25c4beSJani Nikula i915->params.enable_guc, "GuC submission is N/A");
11801158da7SMichal Wajdeczko
1191e58215fSJohn Harrison if (i915->params.enable_guc & ~ENABLE_GUC_MASK)
1204fd4fde8SJohn Harrison gt_info(gt, "Incompatible option enable_guc=%d - %s\n",
1218a25c4beSJani Nikula i915->params.enable_guc, "undocumented flag");
1220f261b24SDaniele Ceraolo Spurio }
1230f261b24SDaniele Ceraolo Spurio
intel_uc_init_early(struct intel_uc * uc)124ca7b2c1bSDaniele Ceraolo Spurio void intel_uc_init_early(struct intel_uc *uc)
1250f261b24SDaniele Ceraolo Spurio {
1261e58215fSJohn Harrison uc_expand_default_options(uc);
1271e58215fSJohn Harrison
128ca7b2c1bSDaniele Ceraolo Spurio intel_guc_init_early(&uc->guc);
129ca7b2c1bSDaniele Ceraolo Spurio intel_huc_init_early(&uc->huc);
130242c4b91SDaniele Ceraolo Spurio intel_gsc_uc_init_early(&uc->gsc);
1310f261b24SDaniele Ceraolo Spurio
13201158da7SMichal Wajdeczko __confirm_options(uc);
1336fbeda0bSMichal Wajdeczko
134bfe5a40aSDaniele Ceraolo Spurio if (intel_uc_wants_guc(uc))
1356fbeda0bSMichal Wajdeczko uc->ops = &uc_ops_on;
1366fbeda0bSMichal Wajdeczko else
1376fbeda0bSMichal Wajdeczko uc->ops = &uc_ops_off;
1380f261b24SDaniele Ceraolo Spurio }
1390f261b24SDaniele Ceraolo Spurio
intel_uc_init_late(struct intel_uc * uc)140481d458cSJohn Harrison void intel_uc_init_late(struct intel_uc *uc)
141481d458cSJohn Harrison {
142481d458cSJohn Harrison intel_guc_init_late(&uc->guc);
143913e013eSDaniele Ceraolo Spurio intel_gsc_uc_load_start(&uc->gsc);
144481d458cSJohn Harrison }
145481d458cSJohn Harrison
intel_uc_driver_late_release(struct intel_uc * uc)1466f76098fSDaniele Ceraolo Spurio void intel_uc_driver_late_release(struct intel_uc *uc)
1470f261b24SDaniele Ceraolo Spurio {
1480f261b24SDaniele Ceraolo Spurio }
1490f261b24SDaniele Ceraolo Spurio
1500f261b24SDaniele Ceraolo Spurio /**
1510f261b24SDaniele Ceraolo Spurio * intel_uc_init_mmio - setup uC MMIO access
152ca7b2c1bSDaniele Ceraolo Spurio * @uc: the intel_uc structure
1530f261b24SDaniele Ceraolo Spurio *
1540f261b24SDaniele Ceraolo Spurio * Setup minimal state necessary for MMIO accesses later in the
1550f261b24SDaniele Ceraolo Spurio * initialization sequence.
1560f261b24SDaniele Ceraolo Spurio */
intel_uc_init_mmio(struct intel_uc * uc)157ca7b2c1bSDaniele Ceraolo Spurio void intel_uc_init_mmio(struct intel_uc *uc)
1580f261b24SDaniele Ceraolo Spurio {
159ca7b2c1bSDaniele Ceraolo Spurio intel_guc_init_send_regs(&uc->guc);
1600f261b24SDaniele Ceraolo Spurio }
1610f261b24SDaniele Ceraolo Spurio
__uc_capture_load_err_log(struct intel_uc * uc)16232ff76e8SMichal Wajdeczko static void __uc_capture_load_err_log(struct intel_uc *uc)
1630f261b24SDaniele Ceraolo Spurio {
16432ff76e8SMichal Wajdeczko struct intel_guc *guc = &uc->guc;
1650f261b24SDaniele Ceraolo Spurio
16632ff76e8SMichal Wajdeczko if (guc->log.vma && !uc->load_err_log)
16732ff76e8SMichal Wajdeczko uc->load_err_log = i915_gem_object_get(guc->log.vma->obj);
1680f261b24SDaniele Ceraolo Spurio }
1690f261b24SDaniele Ceraolo Spurio
__uc_free_load_err_log(struct intel_uc * uc)17032ff76e8SMichal Wajdeczko static void __uc_free_load_err_log(struct intel_uc *uc)
1710f261b24SDaniele Ceraolo Spurio {
17232ff76e8SMichal Wajdeczko struct drm_i915_gem_object *log = fetch_and_zero(&uc->load_err_log);
17332ff76e8SMichal Wajdeczko
17432ff76e8SMichal Wajdeczko if (log)
17532ff76e8SMichal Wajdeczko i915_gem_object_put(log);
1760f261b24SDaniele Ceraolo Spurio }
1770f261b24SDaniele Ceraolo Spurio
intel_uc_driver_remove(struct intel_uc * uc)178a9410a62SDaniele Ceraolo Spurio void intel_uc_driver_remove(struct intel_uc *uc)
179a9410a62SDaniele Ceraolo Spurio {
180a9410a62SDaniele Ceraolo Spurio intel_uc_fini_hw(uc);
181a9410a62SDaniele Ceraolo Spurio intel_uc_fini(uc);
182a9410a62SDaniele Ceraolo Spurio __uc_free_load_err_log(uc);
183a9410a62SDaniele Ceraolo Spurio }
184a9410a62SDaniele Ceraolo Spurio
1850f261b24SDaniele Ceraolo Spurio /*
1860f261b24SDaniele Ceraolo Spurio * Events triggered while CT buffers are disabled are logged in the SCRATCH_15
1870f261b24SDaniele Ceraolo Spurio * register using the same bits used in the CT message payload. Since our
1880f261b24SDaniele Ceraolo Spurio * communication channel with guc is turned off at this point, we can save the
1890f261b24SDaniele Ceraolo Spurio * message and handle it after we turn it back on.
1900f261b24SDaniele Ceraolo Spurio */
guc_clear_mmio_msg(struct intel_guc * guc)1910f261b24SDaniele Ceraolo Spurio static void guc_clear_mmio_msg(struct intel_guc *guc)
1920f261b24SDaniele Ceraolo Spurio {
19384b1ca2fSDaniele Ceraolo Spurio intel_uncore_write(guc_to_gt(guc)->uncore, SOFT_SCRATCH(15), 0);
1940f261b24SDaniele Ceraolo Spurio }
1950f261b24SDaniele Ceraolo Spurio
guc_get_mmio_msg(struct intel_guc * guc)1960f261b24SDaniele Ceraolo Spurio static void guc_get_mmio_msg(struct intel_guc *guc)
1970f261b24SDaniele Ceraolo Spurio {
1980f261b24SDaniele Ceraolo Spurio u32 val;
1990f261b24SDaniele Ceraolo Spurio
2000f261b24SDaniele Ceraolo Spurio spin_lock_irq(&guc->irq_lock);
2010f261b24SDaniele Ceraolo Spurio
20284b1ca2fSDaniele Ceraolo Spurio val = intel_uncore_read(guc_to_gt(guc)->uncore, SOFT_SCRATCH(15));
2030f261b24SDaniele Ceraolo Spurio guc->mmio_msg |= val & guc->msg_enabled_mask;
2040f261b24SDaniele Ceraolo Spurio
2050f261b24SDaniele Ceraolo Spurio /*
2060f261b24SDaniele Ceraolo Spurio * clear all events, including the ones we're not currently servicing,
2070f261b24SDaniele Ceraolo Spurio * to make sure we don't try to process a stale message if we enable
2080f261b24SDaniele Ceraolo Spurio * handling of more events later.
2090f261b24SDaniele Ceraolo Spurio */
2100f261b24SDaniele Ceraolo Spurio guc_clear_mmio_msg(guc);
2110f261b24SDaniele Ceraolo Spurio
2120f261b24SDaniele Ceraolo Spurio spin_unlock_irq(&guc->irq_lock);
2130f261b24SDaniele Ceraolo Spurio }
2140f261b24SDaniele Ceraolo Spurio
guc_handle_mmio_msg(struct intel_guc * guc)2150f261b24SDaniele Ceraolo Spurio static void guc_handle_mmio_msg(struct intel_guc *guc)
2160f261b24SDaniele Ceraolo Spurio {
2170f261b24SDaniele Ceraolo Spurio /* we need communication to be enabled to reply to GuC */
2185db18567SDaniele Ceraolo Spurio GEM_BUG_ON(!intel_guc_ct_enabled(&guc->ct));
2190f261b24SDaniele Ceraolo Spurio
22001666975STvrtko Ursulin spin_lock_irq(&guc->irq_lock);
22101666975STvrtko Ursulin if (guc->mmio_msg) {
2220f261b24SDaniele Ceraolo Spurio intel_guc_to_host_process_recv_msg(guc, &guc->mmio_msg, 1);
2230f261b24SDaniele Ceraolo Spurio guc->mmio_msg = 0;
2240f261b24SDaniele Ceraolo Spurio }
22501666975STvrtko Ursulin spin_unlock_irq(&guc->irq_lock);
22601666975STvrtko Ursulin }
2270f261b24SDaniele Ceraolo Spurio
guc_enable_communication(struct intel_guc * guc)2280f261b24SDaniele Ceraolo Spurio static int guc_enable_communication(struct intel_guc *guc)
2290f261b24SDaniele Ceraolo Spurio {
2302f87c053STvrtko Ursulin struct intel_gt *gt = guc_to_gt(guc);
2312f87c053STvrtko Ursulin struct drm_i915_private *i915 = gt->i915;
2320f261b24SDaniele Ceraolo Spurio int ret;
2330f261b24SDaniele Ceraolo Spurio
2345db18567SDaniele Ceraolo Spurio GEM_BUG_ON(intel_guc_ct_enabled(&guc->ct));
235602776f9SDaniele Ceraolo Spurio
236dd6e38dfSJanusz Krzysztofik ret = i915_inject_probe_error(i915, -ENXIO);
2375d1ef2b4SMichal Wajdeczko if (ret)
2385d1ef2b4SMichal Wajdeczko return ret;
2395d1ef2b4SMichal Wajdeczko
2400f261b24SDaniele Ceraolo Spurio ret = intel_guc_ct_enable(&guc->ct);
2410f261b24SDaniele Ceraolo Spurio if (ret)
2420f261b24SDaniele Ceraolo Spurio return ret;
2430f261b24SDaniele Ceraolo Spurio
2440f261b24SDaniele Ceraolo Spurio /* check for mmio messages received before/during the CT enable */
2450f261b24SDaniele Ceraolo Spurio guc_get_mmio_msg(guc);
2460f261b24SDaniele Ceraolo Spurio guc_handle_mmio_msg(guc);
2470f261b24SDaniele Ceraolo Spurio
248e5a1ad03SMatthew Brost intel_guc_enable_interrupts(guc);
2490f261b24SDaniele Ceraolo Spurio
2500f261b24SDaniele Ceraolo Spurio /* check for CT messages received before we enabled interrupts */
25103d2c54dSMatt Roper spin_lock_irq(gt->irq_lock);
2528c69bd74SDaniele Ceraolo Spurio intel_guc_ct_event_handler(&guc->ct);
25303d2c54dSMatt Roper spin_unlock_irq(gt->irq_lock);
2540f261b24SDaniele Ceraolo Spurio
2552f8c06cbSMichal Wajdeczko guc_dbg(guc, "communication enabled\n");
2560f261b24SDaniele Ceraolo Spurio
2570f261b24SDaniele Ceraolo Spurio return 0;
2580f261b24SDaniele Ceraolo Spurio }
2590f261b24SDaniele Ceraolo Spurio
guc_disable_communication(struct intel_guc * guc)260e627ad50SDaniele Ceraolo Spurio static void guc_disable_communication(struct intel_guc *guc)
2610f261b24SDaniele Ceraolo Spurio {
2620f261b24SDaniele Ceraolo Spurio /*
2630f261b24SDaniele Ceraolo Spurio * Events generated during or after CT disable are logged by guc in
2640f261b24SDaniele Ceraolo Spurio * via mmio. Make sure the register is clear before disabling CT since
2650f261b24SDaniele Ceraolo Spurio * all events we cared about have already been processed via CT.
2660f261b24SDaniele Ceraolo Spurio */
2670f261b24SDaniele Ceraolo Spurio guc_clear_mmio_msg(guc);
2680f261b24SDaniele Ceraolo Spurio
269e5a1ad03SMatthew Brost intel_guc_disable_interrupts(guc);
2700f261b24SDaniele Ceraolo Spurio
2710f261b24SDaniele Ceraolo Spurio intel_guc_ct_disable(&guc->ct);
2720f261b24SDaniele Ceraolo Spurio
2730f261b24SDaniele Ceraolo Spurio /*
2740f261b24SDaniele Ceraolo Spurio * Check for messages received during/after the CT disable. We do not
2750f261b24SDaniele Ceraolo Spurio * expect any messages to have arrived via CT between the interrupt
2760f261b24SDaniele Ceraolo Spurio * disable and the CT disable because GuC should've been idle until we
2770f261b24SDaniele Ceraolo Spurio * triggered the CT disable protocol.
2780f261b24SDaniele Ceraolo Spurio */
2790f261b24SDaniele Ceraolo Spurio guc_get_mmio_msg(guc);
2800f261b24SDaniele Ceraolo Spurio
2812f8c06cbSMichal Wajdeczko guc_dbg(guc, "communication disabled\n");
2820f261b24SDaniele Ceraolo Spurio }
2830f261b24SDaniele Ceraolo Spurio
__uc_fetch_firmwares(struct intel_uc * uc)28439ddb863SMichal Wajdeczko static void __uc_fetch_firmwares(struct intel_uc *uc)
2850f261b24SDaniele Ceraolo Spurio {
2862f8c06cbSMichal Wajdeczko struct intel_gt *gt = uc_to_gt(uc);
2874157a962SMichal Wajdeczko int err;
288ca7b2c1bSDaniele Ceraolo Spurio
289bfe5a40aSDaniele Ceraolo Spurio GEM_BUG_ON(!intel_uc_wants_guc(uc));
2900f261b24SDaniele Ceraolo Spurio
291cb1b7ad0SMichal Wajdeczko err = intel_uc_fw_fetch(&uc->guc.fw);
2929459fd59SMichał Winiarski if (err) {
2939459fd59SMichał Winiarski /* Make sure we transition out of transient "SELECTED" state */
2949459fd59SMichał Winiarski if (intel_uc_wants_huc(uc)) {
2952f8c06cbSMichal Wajdeczko gt_dbg(gt, "Failed to fetch GuC fw (%pe) disabling HuC\n", ERR_PTR(err));
2969459fd59SMichał Winiarski intel_uc_fw_change_status(&uc->huc.fw,
2979459fd59SMichał Winiarski INTEL_UC_FIRMWARE_ERROR);
2989459fd59SMichał Winiarski }
2999459fd59SMichał Winiarski
300242c4b91SDaniele Ceraolo Spurio if (intel_uc_wants_gsc_uc(uc)) {
3012f8c06cbSMichal Wajdeczko gt_dbg(gt, "Failed to fetch GuC fw (%pe) disabling GSC\n", ERR_PTR(err));
302242c4b91SDaniele Ceraolo Spurio intel_uc_fw_change_status(&uc->gsc.fw,
303242c4b91SDaniele Ceraolo Spurio INTEL_UC_FIRMWARE_ERROR);
304242c4b91SDaniele Ceraolo Spurio }
305242c4b91SDaniele Ceraolo Spurio
3064157a962SMichal Wajdeczko return;
3079459fd59SMichał Winiarski }
3080f261b24SDaniele Ceraolo Spurio
309bfe5a40aSDaniele Ceraolo Spurio if (intel_uc_wants_huc(uc))
310cb1b7ad0SMichal Wajdeczko intel_uc_fw_fetch(&uc->huc.fw);
311242c4b91SDaniele Ceraolo Spurio
312242c4b91SDaniele Ceraolo Spurio if (intel_uc_wants_gsc_uc(uc))
313242c4b91SDaniele Ceraolo Spurio intel_uc_fw_fetch(&uc->gsc.fw);
3140f261b24SDaniele Ceraolo Spurio }
3150f261b24SDaniele Ceraolo Spurio
__uc_cleanup_firmwares(struct intel_uc * uc)31639ddb863SMichal Wajdeczko static void __uc_cleanup_firmwares(struct intel_uc *uc)
3170f261b24SDaniele Ceraolo Spurio {
318242c4b91SDaniele Ceraolo Spurio intel_uc_fw_cleanup_fetch(&uc->gsc.fw);
319ca7b2c1bSDaniele Ceraolo Spurio intel_uc_fw_cleanup_fetch(&uc->huc.fw);
320ca7b2c1bSDaniele Ceraolo Spurio intel_uc_fw_cleanup_fetch(&uc->guc.fw);
3210f261b24SDaniele Ceraolo Spurio }
3220f261b24SDaniele Ceraolo Spurio
__uc_init(struct intel_uc * uc)3233acffa8cSDaniele Ceraolo Spurio static int __uc_init(struct intel_uc *uc)
3240f261b24SDaniele Ceraolo Spurio {
325ca7b2c1bSDaniele Ceraolo Spurio struct intel_guc *guc = &uc->guc;
326ca7b2c1bSDaniele Ceraolo Spurio struct intel_huc *huc = &uc->huc;
3270f261b24SDaniele Ceraolo Spurio int ret;
3280f261b24SDaniele Ceraolo Spurio
329bfe5a40aSDaniele Ceraolo Spurio GEM_BUG_ON(!intel_uc_wants_guc(uc));
330bfe5a40aSDaniele Ceraolo Spurio
331bfe5a40aSDaniele Ceraolo Spurio if (!intel_uc_uses_guc(uc))
3323acffa8cSDaniele Ceraolo Spurio return 0;
3333acffa8cSDaniele Ceraolo Spurio
3343acffa8cSDaniele Ceraolo Spurio if (i915_inject_probe_failure(uc_to_gt(uc)->i915))
3353acffa8cSDaniele Ceraolo Spurio return -ENOMEM;
3360f261b24SDaniele Ceraolo Spurio
3370f261b24SDaniele Ceraolo Spurio ret = intel_guc_init(guc);
3383acffa8cSDaniele Ceraolo Spurio if (ret)
3393acffa8cSDaniele Ceraolo Spurio return ret;
3403acffa8cSDaniele Ceraolo Spurio
34156ca3117SDaniele Ceraolo Spurio if (intel_uc_uses_huc(uc))
34256ca3117SDaniele Ceraolo Spurio intel_huc_init(huc);
3430f261b24SDaniele Ceraolo Spurio
344242c4b91SDaniele Ceraolo Spurio if (intel_uc_uses_gsc_uc(uc))
345242c4b91SDaniele Ceraolo Spurio intel_gsc_uc_init(&uc->gsc);
346242c4b91SDaniele Ceraolo Spurio
3473acffa8cSDaniele Ceraolo Spurio return 0;
3480f261b24SDaniele Ceraolo Spurio }
3490f261b24SDaniele Ceraolo Spurio
__uc_fini(struct intel_uc * uc)350cc93f7b0SMichal Wajdeczko static void __uc_fini(struct intel_uc *uc)
3510f261b24SDaniele Ceraolo Spurio {
352242c4b91SDaniele Ceraolo Spurio intel_gsc_uc_fini(&uc->gsc);
353ca7b2c1bSDaniele Ceraolo Spurio intel_huc_fini(&uc->huc);
354e26b6d43SChris Wilson intel_guc_fini(&uc->guc);
3550f261b24SDaniele Ceraolo Spurio }
3560f261b24SDaniele Ceraolo Spurio
__uc_sanitize(struct intel_uc * uc)357771051eaSMichal Wajdeczko static int __uc_sanitize(struct intel_uc *uc)
3580f261b24SDaniele Ceraolo Spurio {
359ca7b2c1bSDaniele Ceraolo Spurio struct intel_guc *guc = &uc->guc;
360ca7b2c1bSDaniele Ceraolo Spurio struct intel_huc *huc = &uc->huc;
3610f261b24SDaniele Ceraolo Spurio
36234f0a20fSMichal Wajdeczko GEM_BUG_ON(!intel_uc_supports_guc(uc));
3630f261b24SDaniele Ceraolo Spurio
3640f261b24SDaniele Ceraolo Spurio intel_huc_sanitize(huc);
3650f261b24SDaniele Ceraolo Spurio intel_guc_sanitize(guc);
3660f261b24SDaniele Ceraolo Spurio
367771051eaSMichal Wajdeczko return __intel_uc_reset_hw(uc);
3680f261b24SDaniele Ceraolo Spurio }
3690f261b24SDaniele Ceraolo Spurio
37063064d82SDaniele Ceraolo Spurio /* Initialize and verify the uC regs related to uC positioning in WOPCM */
uc_init_wopcm(struct intel_uc * uc)37163064d82SDaniele Ceraolo Spurio static int uc_init_wopcm(struct intel_uc *uc)
37263064d82SDaniele Ceraolo Spurio {
37363064d82SDaniele Ceraolo Spurio struct intel_gt *gt = uc_to_gt(uc);
37463064d82SDaniele Ceraolo Spurio struct intel_uncore *uncore = gt->uncore;
375ee71434eSAravind Iddamsetty u32 base = intel_wopcm_guc_base(>->wopcm);
376ee71434eSAravind Iddamsetty u32 size = intel_wopcm_guc_size(>->wopcm);
377356c4848SMichal Wajdeczko u32 huc_agent = intel_uc_uses_huc(uc) ? HUC_LOADING_AGENT_GUC : 0;
37863064d82SDaniele Ceraolo Spurio u32 mask;
37963064d82SDaniele Ceraolo Spurio int err;
38063064d82SDaniele Ceraolo Spurio
3816bd0fbe1SMichal Wajdeczko if (unlikely(!base || !size)) {
3822f8c06cbSMichal Wajdeczko gt_probe_error(gt, "Unsuccessful WOPCM partitioning\n");
3836bd0fbe1SMichal Wajdeczko return -E2BIG;
3846bd0fbe1SMichal Wajdeczko }
3856bd0fbe1SMichal Wajdeczko
38657a68c35SMichal Wajdeczko GEM_BUG_ON(!intel_uc_supports_guc(uc));
38763064d82SDaniele Ceraolo Spurio GEM_BUG_ON(!(base & GUC_WOPCM_OFFSET_MASK));
38863064d82SDaniele Ceraolo Spurio GEM_BUG_ON(base & ~GUC_WOPCM_OFFSET_MASK);
38963064d82SDaniele Ceraolo Spurio GEM_BUG_ON(!(size & GUC_WOPCM_SIZE_MASK));
39063064d82SDaniele Ceraolo Spurio GEM_BUG_ON(size & ~GUC_WOPCM_SIZE_MASK);
39163064d82SDaniele Ceraolo Spurio
392dd6e38dfSJanusz Krzysztofik err = i915_inject_probe_error(gt->i915, -ENXIO);
3935d1ef2b4SMichal Wajdeczko if (err)
3945d1ef2b4SMichal Wajdeczko return err;
3955d1ef2b4SMichal Wajdeczko
39663064d82SDaniele Ceraolo Spurio mask = GUC_WOPCM_SIZE_MASK | GUC_WOPCM_SIZE_LOCKED;
39763064d82SDaniele Ceraolo Spurio err = intel_uncore_write_and_verify(uncore, GUC_WOPCM_SIZE, size, mask,
39863064d82SDaniele Ceraolo Spurio size | GUC_WOPCM_SIZE_LOCKED);
39963064d82SDaniele Ceraolo Spurio if (err)
40063064d82SDaniele Ceraolo Spurio goto err_out;
40163064d82SDaniele Ceraolo Spurio
40263064d82SDaniele Ceraolo Spurio mask = GUC_WOPCM_OFFSET_MASK | GUC_WOPCM_OFFSET_VALID | huc_agent;
40363064d82SDaniele Ceraolo Spurio err = intel_uncore_write_and_verify(uncore, DMA_GUC_WOPCM_OFFSET,
40463064d82SDaniele Ceraolo Spurio base | huc_agent, mask,
40563064d82SDaniele Ceraolo Spurio base | huc_agent |
40663064d82SDaniele Ceraolo Spurio GUC_WOPCM_OFFSET_VALID);
40763064d82SDaniele Ceraolo Spurio if (err)
40863064d82SDaniele Ceraolo Spurio goto err_out;
40963064d82SDaniele Ceraolo Spurio
41063064d82SDaniele Ceraolo Spurio return 0;
41163064d82SDaniele Ceraolo Spurio
41263064d82SDaniele Ceraolo Spurio err_out:
4132f8c06cbSMichal Wajdeczko gt_probe_error(gt, "Failed to init uC WOPCM registers!\n");
4142f8c06cbSMichal Wajdeczko gt_probe_error(gt, "%s(%#x)=%#x\n", "DMA_GUC_WOPCM_OFFSET",
415a0752c87SMichal Wajdeczko i915_mmio_reg_offset(DMA_GUC_WOPCM_OFFSET),
41663064d82SDaniele Ceraolo Spurio intel_uncore_read(uncore, DMA_GUC_WOPCM_OFFSET));
4172f8c06cbSMichal Wajdeczko gt_probe_error(gt, "%s(%#x)=%#x\n", "GUC_WOPCM_SIZE",
418a0752c87SMichal Wajdeczko i915_mmio_reg_offset(GUC_WOPCM_SIZE),
41963064d82SDaniele Ceraolo Spurio intel_uncore_read(uncore, GUC_WOPCM_SIZE));
42063064d82SDaniele Ceraolo Spurio
42163064d82SDaniele Ceraolo Spurio return err;
42263064d82SDaniele Ceraolo Spurio }
42363064d82SDaniele Ceraolo Spurio
uc_is_wopcm_locked(struct intel_uc * uc)424ee402140SMichal Wajdeczko static bool uc_is_wopcm_locked(struct intel_uc *uc)
425ee402140SMichal Wajdeczko {
426ee402140SMichal Wajdeczko struct intel_gt *gt = uc_to_gt(uc);
427ee402140SMichal Wajdeczko struct intel_uncore *uncore = gt->uncore;
428ee402140SMichal Wajdeczko
429ee402140SMichal Wajdeczko return (intel_uncore_read(uncore, GUC_WOPCM_SIZE) & GUC_WOPCM_SIZE_LOCKED) ||
430ee402140SMichal Wajdeczko (intel_uncore_read(uncore, DMA_GUC_WOPCM_OFFSET) & GUC_WOPCM_OFFSET_VALID);
431ee402140SMichal Wajdeczko }
432ee402140SMichal Wajdeczko
__uc_check_hw(struct intel_uc * uc)4336fbeda0bSMichal Wajdeczko static int __uc_check_hw(struct intel_uc *uc)
4340f261b24SDaniele Ceraolo Spurio {
435edba7789SJohn Harrison if (uc->fw_table_invalid)
436edba7789SJohn Harrison return -EIO;
437edba7789SJohn Harrison
43857a68c35SMichal Wajdeczko if (!intel_uc_supports_guc(uc))
4390f261b24SDaniele Ceraolo Spurio return 0;
4400f261b24SDaniele Ceraolo Spurio
441ee402140SMichal Wajdeczko /*
442ee402140SMichal Wajdeczko * We can silently continue without GuC only if it was never enabled
443ee402140SMichal Wajdeczko * before on this system after reboot, otherwise we risk GPU hangs.
444ee402140SMichal Wajdeczko * To check if GuC was loaded before we look at WOPCM registers.
445ee402140SMichal Wajdeczko */
4466fbeda0bSMichal Wajdeczko if (uc_is_wopcm_locked(uc))
4476fbeda0bSMichal Wajdeczko return -EIO;
4486fbeda0bSMichal Wajdeczko
449356c4848SMichal Wajdeczko return 0;
4506fbeda0bSMichal Wajdeczko }
4516fbeda0bSMichal Wajdeczko
print_fw_ver(struct intel_gt * gt,struct intel_uc_fw * fw)4522f8c06cbSMichal Wajdeczko static void print_fw_ver(struct intel_gt *gt, struct intel_uc_fw *fw)
453afd088acSJohn Harrison {
4542f8c06cbSMichal Wajdeczko gt_info(gt, "%s firmware %s version %u.%u.%u\n",
455665ae9c9SJohn Harrison intel_uc_fw_type_repr(fw->type), fw->file_selected.path,
45692fcd248SJohn Harrison fw->file_selected.ver.major,
45792fcd248SJohn Harrison fw->file_selected.ver.minor,
45892fcd248SJohn Harrison fw->file_selected.ver.patch);
459afd088acSJohn Harrison }
460afd088acSJohn Harrison
__uc_init_hw(struct intel_uc * uc)4616fbeda0bSMichal Wajdeczko static int __uc_init_hw(struct intel_uc *uc)
4626fbeda0bSMichal Wajdeczko {
4632f8c06cbSMichal Wajdeczko struct intel_gt *gt = uc_to_gt(uc);
4642f8c06cbSMichal Wajdeczko struct drm_i915_private *i915 = gt->i915;
4656fbeda0bSMichal Wajdeczko struct intel_guc *guc = &uc->guc;
4666fbeda0bSMichal Wajdeczko struct intel_huc *huc = &uc->huc;
4676fbeda0bSMichal Wajdeczko int ret, attempts;
468621b6783SAshutosh Dixit bool pl1en = false;
4696fbeda0bSMichal Wajdeczko
4706fbeda0bSMichal Wajdeczko GEM_BUG_ON(!intel_uc_supports_guc(uc));
471bfe5a40aSDaniele Ceraolo Spurio GEM_BUG_ON(!intel_uc_wants_guc(uc));
472356c4848SMichal Wajdeczko
4732f8c06cbSMichal Wajdeczko print_fw_ver(gt, &guc->fw);
474afd088acSJohn Harrison
475afd088acSJohn Harrison if (intel_uc_uses_huc(uc))
4762f8c06cbSMichal Wajdeczko print_fw_ver(gt, &huc->fw);
477afd088acSJohn Harrison
47842f96e5bSDaniele Ceraolo Spurio if (!intel_uc_fw_is_loadable(&guc->fw)) {
4796fbeda0bSMichal Wajdeczko ret = __uc_check_hw(uc) ||
480ee402140SMichal Wajdeczko intel_uc_fw_is_overridden(&guc->fw) ||
481202c98e7SDaniele Ceraolo Spurio intel_uc_wants_guc_submission(uc) ?
482ee402140SMichal Wajdeczko intel_uc_fw_status_to_error(guc->fw.status) : 0;
483ae7a3166SMichal Wajdeczko goto err_out;
484ae7a3166SMichal Wajdeczko }
485ae7a3166SMichal Wajdeczko
48663064d82SDaniele Ceraolo Spurio ret = uc_init_wopcm(uc);
48763064d82SDaniele Ceraolo Spurio if (ret)
48863064d82SDaniele Ceraolo Spurio goto err_out;
48963064d82SDaniele Ceraolo Spurio
490e5a1ad03SMatthew Brost intel_guc_reset_interrupts(guc);
4910f261b24SDaniele Ceraolo Spurio
4920f261b24SDaniele Ceraolo Spurio /* WaEnableuKernelHeaderValidFix:skl */
4930f261b24SDaniele Ceraolo Spurio /* WaEnableGuCBootHashCheckNotSet:skl,bxt,kbl */
494c816723bSLucas De Marchi if (GRAPHICS_VER(i915) == 9)
4950f261b24SDaniele Ceraolo Spurio attempts = 3;
4960f261b24SDaniele Ceraolo Spurio else
4970f261b24SDaniele Ceraolo Spurio attempts = 1;
4980f261b24SDaniele Ceraolo Spurio
4991b44019aSAshutosh Dixit /* Disable a potentially low PL1 power limit to allow freq to be raised */
5001b44019aSAshutosh Dixit i915_hwmon_power_max_disable(gt->i915, &pl1en);
5011b44019aSAshutosh Dixit
5021c40d40fSVinay Belgaumkar intel_rps_raise_unslice(&uc_to_gt(uc)->rps);
5031c40d40fSVinay Belgaumkar
5040f261b24SDaniele Ceraolo Spurio while (attempts--) {
5050f261b24SDaniele Ceraolo Spurio /*
5060f261b24SDaniele Ceraolo Spurio * Always reset the GuC just before (re)loading, so
5070f261b24SDaniele Ceraolo Spurio * that the state and timing are fairly predictable
5080f261b24SDaniele Ceraolo Spurio */
509771051eaSMichal Wajdeczko ret = __uc_sanitize(uc);
5100f261b24SDaniele Ceraolo Spurio if (ret)
5111b44019aSAshutosh Dixit goto err_rps;
5120f261b24SDaniele Ceraolo Spurio
513a8dc0f6dSMichal Wajdeczko intel_huc_fw_upload(huc);
5140f261b24SDaniele Ceraolo Spurio intel_guc_ads_reset(guc);
5152bf8fb39SDaniele Ceraolo Spurio intel_guc_write_params(guc);
5160f261b24SDaniele Ceraolo Spurio ret = intel_guc_fw_upload(guc);
5170f261b24SDaniele Ceraolo Spurio if (ret == 0)
5180f261b24SDaniele Ceraolo Spurio break;
5190f261b24SDaniele Ceraolo Spurio
5202f8c06cbSMichal Wajdeczko gt_dbg(gt, "GuC fw load failed (%pe) will reset and retry %d more time(s)\n",
5212f8c06cbSMichal Wajdeczko ERR_PTR(ret), attempts);
5220f261b24SDaniele Ceraolo Spurio }
5230f261b24SDaniele Ceraolo Spurio
5240f261b24SDaniele Ceraolo Spurio /* Did we succeded or run out of retries? */
5250f261b24SDaniele Ceraolo Spurio if (ret)
5260f261b24SDaniele Ceraolo Spurio goto err_log_capture;
5270f261b24SDaniele Ceraolo Spurio
5280f261b24SDaniele Ceraolo Spurio ret = guc_enable_communication(guc);
5290f261b24SDaniele Ceraolo Spurio if (ret)
5300f261b24SDaniele Ceraolo Spurio goto err_log_capture;
5310f261b24SDaniele Ceraolo Spurio
5326f67930aSDaniele Ceraolo Spurio /*
5336f67930aSDaniele Ceraolo Spurio * GSC-loaded HuC is authenticated by the GSC, so we don't need to
5346f67930aSDaniele Ceraolo Spurio * trigger the auth here. However, given that the HuC loaded this way
5356f67930aSDaniele Ceraolo Spurio * survive GT reset, we still need to update our SW bookkeeping to make
5366f67930aSDaniele Ceraolo Spurio * sure it reflects the correct HW status.
5376f67930aSDaniele Ceraolo Spurio */
5386f67930aSDaniele Ceraolo Spurio if (intel_huc_is_loaded_by_gsc(huc))
5396f67930aSDaniele Ceraolo Spurio intel_huc_update_auth_status(huc);
5406f67930aSDaniele Ceraolo Spurio else
54108872cb1SDaniele Ceraolo Spurio intel_huc_auth(huc, INTEL_HUC_AUTH_BY_GUC);
5420f261b24SDaniele Ceraolo Spurio
543cd414f4fSJohn Harrison if (intel_uc_uses_guc_submission(uc)) {
544cd414f4fSJohn Harrison ret = intel_guc_submission_enable(guc);
545cd414f4fSJohn Harrison if (ret)
546cd414f4fSJohn Harrison goto err_log_capture;
547cd414f4fSJohn Harrison }
5480f261b24SDaniele Ceraolo Spurio
54963c0eb30SVinay Belgaumkar if (intel_uc_uses_guc_slpc(uc)) {
55063c0eb30SVinay Belgaumkar ret = intel_guc_slpc_enable(&guc->slpc);
55163c0eb30SVinay Belgaumkar if (ret)
55263c0eb30SVinay Belgaumkar goto err_submission;
5531c40d40fSVinay Belgaumkar } else {
5541c40d40fSVinay Belgaumkar /* Restore GT back to RPn for non-SLPC path */
5551c40d40fSVinay Belgaumkar intel_rps_lower_unslice(&uc_to_gt(uc)->rps);
55663c0eb30SVinay Belgaumkar }
55763c0eb30SVinay Belgaumkar
5581b44019aSAshutosh Dixit i915_hwmon_power_max_restore(gt->i915, pl1en);
5591b44019aSAshutosh Dixit
5604fd4fde8SJohn Harrison guc_info(guc, "submission %s\n", str_enabled_disabled(intel_uc_uses_guc_submission(uc)));
5614fd4fde8SJohn Harrison guc_info(guc, "SLPC %s\n", str_enabled_disabled(intel_uc_uses_guc_slpc(uc)));
56263c0eb30SVinay Belgaumkar
5630f261b24SDaniele Ceraolo Spurio return 0;
5640f261b24SDaniele Ceraolo Spurio
5650f261b24SDaniele Ceraolo Spurio /*
5660f261b24SDaniele Ceraolo Spurio * We've failed to load the firmware :(
5670f261b24SDaniele Ceraolo Spurio */
56863c0eb30SVinay Belgaumkar err_submission:
56963c0eb30SVinay Belgaumkar intel_guc_submission_disable(guc);
5700f261b24SDaniele Ceraolo Spurio err_log_capture:
57132ff76e8SMichal Wajdeczko __uc_capture_load_err_log(uc);
5721b44019aSAshutosh Dixit err_rps:
5731c40d40fSVinay Belgaumkar /* Return GT back to RPn */
5741c40d40fSVinay Belgaumkar intel_rps_lower_unslice(&uc_to_gt(uc)->rps);
5751c40d40fSVinay Belgaumkar
5761b44019aSAshutosh Dixit i915_hwmon_power_max_restore(gt->i915, pl1en);
5771b44019aSAshutosh Dixit err_out:
578ca7b2c1bSDaniele Ceraolo Spurio __uc_sanitize(uc);
5790f261b24SDaniele Ceraolo Spurio
580ee402140SMichal Wajdeczko if (!ret) {
5812f8c06cbSMichal Wajdeczko gt_notice(gt, "GuC is uninitialized\n");
582ee402140SMichal Wajdeczko /* We want to run without GuC submission */
583ee402140SMichal Wajdeczko return 0;
584ee402140SMichal Wajdeczko }
585ee402140SMichal Wajdeczko
5862f8c06cbSMichal Wajdeczko gt_probe_error(gt, "GuC initialization failed %pe\n", ERR_PTR(ret));
587a5f978c3SMichal Wajdeczko
588a5f978c3SMichal Wajdeczko /* We want to keep KMS alive */
589a5f978c3SMichal Wajdeczko return -EIO;
5900f261b24SDaniele Ceraolo Spurio }
5910f261b24SDaniele Ceraolo Spurio
__uc_fini_hw(struct intel_uc * uc)5926fbeda0bSMichal Wajdeczko static void __uc_fini_hw(struct intel_uc *uc)
5930f261b24SDaniele Ceraolo Spurio {
594ca7b2c1bSDaniele Ceraolo Spurio struct intel_guc *guc = &uc->guc;
5950f261b24SDaniele Ceraolo Spurio
596e85de177SMichal Wajdeczko if (!intel_guc_is_fw_running(guc))
5970f261b24SDaniele Ceraolo Spurio return;
5980f261b24SDaniele Ceraolo Spurio
599202c98e7SDaniele Ceraolo Spurio if (intel_uc_uses_guc_submission(uc))
6000f261b24SDaniele Ceraolo Spurio intel_guc_submission_disable(guc);
6010f261b24SDaniele Ceraolo Spurio
602ca7b2c1bSDaniele Ceraolo Spurio __uc_sanitize(uc);
6030f261b24SDaniele Ceraolo Spurio }
6040f261b24SDaniele Ceraolo Spurio
6050f261b24SDaniele Ceraolo Spurio /**
6060f261b24SDaniele Ceraolo Spurio * intel_uc_reset_prepare - Prepare for reset
607ca7b2c1bSDaniele Ceraolo Spurio * @uc: the intel_uc structure
6080f261b24SDaniele Ceraolo Spurio *
6090f261b24SDaniele Ceraolo Spurio * Preparing for full gpu reset.
6100f261b24SDaniele Ceraolo Spurio */
intel_uc_reset_prepare(struct intel_uc * uc)611ca7b2c1bSDaniele Ceraolo Spurio void intel_uc_reset_prepare(struct intel_uc *uc)
6120f261b24SDaniele Ceraolo Spurio {
613ca7b2c1bSDaniele Ceraolo Spurio struct intel_guc *guc = &uc->guc;
6140f261b24SDaniele Ceraolo Spurio
615d75dc57fSJohn Harrison uc->reset_in_progress = true;
616d75dc57fSJohn Harrison
617eb5e7da7SMatthew Brost /* Nothing to do if GuC isn't supported */
618eb5e7da7SMatthew Brost if (!intel_uc_supports_guc(uc))
6190f261b24SDaniele Ceraolo Spurio return;
6200f261b24SDaniele Ceraolo Spurio
621eb5e7da7SMatthew Brost /* Firmware expected to be running when this function is called */
622eb5e7da7SMatthew Brost if (!intel_guc_is_ready(guc))
623eb5e7da7SMatthew Brost goto sanitize;
624eb5e7da7SMatthew Brost
625eb5e7da7SMatthew Brost if (intel_uc_uses_guc_submission(uc))
626eb5e7da7SMatthew Brost intel_guc_submission_reset_prepare(guc);
627eb5e7da7SMatthew Brost
628eb5e7da7SMatthew Brost sanitize:
629ca7b2c1bSDaniele Ceraolo Spurio __uc_sanitize(uc);
6300f261b24SDaniele Ceraolo Spurio }
6310f261b24SDaniele Ceraolo Spurio
intel_uc_reset(struct intel_uc * uc,intel_engine_mask_t stalled)632303760aaSUmesh Nerlige Ramappa void intel_uc_reset(struct intel_uc *uc, intel_engine_mask_t stalled)
633eb5e7da7SMatthew Brost {
634eb5e7da7SMatthew Brost struct intel_guc *guc = &uc->guc;
635eb5e7da7SMatthew Brost
636eb5e7da7SMatthew Brost /* Firmware can not be running when this function is called */
637eb5e7da7SMatthew Brost if (intel_uc_uses_guc_submission(uc))
638eb5e7da7SMatthew Brost intel_guc_submission_reset(guc, stalled);
639eb5e7da7SMatthew Brost }
640eb5e7da7SMatthew Brost
intel_uc_reset_finish(struct intel_uc * uc)641eb5e7da7SMatthew Brost void intel_uc_reset_finish(struct intel_uc *uc)
642eb5e7da7SMatthew Brost {
643eb5e7da7SMatthew Brost struct intel_guc *guc = &uc->guc;
644eb5e7da7SMatthew Brost
645d75dc57fSJohn Harrison uc->reset_in_progress = false;
646d75dc57fSJohn Harrison
647eb5e7da7SMatthew Brost /* Firmware expected to be running when this function is called */
648eb5e7da7SMatthew Brost if (intel_guc_is_fw_running(guc) && intel_uc_uses_guc_submission(uc))
649eb5e7da7SMatthew Brost intel_guc_submission_reset_finish(guc);
650eb5e7da7SMatthew Brost }
651eb5e7da7SMatthew Brost
intel_uc_cancel_requests(struct intel_uc * uc)652eb5e7da7SMatthew Brost void intel_uc_cancel_requests(struct intel_uc *uc)
653eb5e7da7SMatthew Brost {
654eb5e7da7SMatthew Brost struct intel_guc *guc = &uc->guc;
655eb5e7da7SMatthew Brost
656eb5e7da7SMatthew Brost /* Firmware can not be running when this function is called */
657eb5e7da7SMatthew Brost if (intel_uc_uses_guc_submission(uc))
658eb5e7da7SMatthew Brost intel_guc_submission_cancel_requests(guc);
659eb5e7da7SMatthew Brost }
660eb5e7da7SMatthew Brost
intel_uc_runtime_suspend(struct intel_uc * uc)661ca7b2c1bSDaniele Ceraolo Spurio void intel_uc_runtime_suspend(struct intel_uc *uc)
6620f261b24SDaniele Ceraolo Spurio {
663ca7b2c1bSDaniele Ceraolo Spurio struct intel_guc *guc = &uc->guc;
6640f261b24SDaniele Ceraolo Spurio
665a187f13dSDaniele Ceraolo Spurio if (!intel_guc_is_ready(guc)) {
666a187f13dSDaniele Ceraolo Spurio guc->interrupts.enabled = false;
6670f261b24SDaniele Ceraolo Spurio return;
668a187f13dSDaniele Ceraolo Spurio }
6690f261b24SDaniele Ceraolo Spurio
670cad46a33SMatthew Brost /*
671cad46a33SMatthew Brost * Wait for any outstanding CTB before tearing down communication /w the
672cad46a33SMatthew Brost * GuC.
673cad46a33SMatthew Brost */
674cad46a33SMatthew Brost #define OUTSTANDING_CTB_TIMEOUT_PERIOD (HZ / 5)
675cad46a33SMatthew Brost intel_guc_wait_for_pending_msg(guc, &guc->outstanding_submission_g2h,
676cad46a33SMatthew Brost false, OUTSTANDING_CTB_TIMEOUT_PERIOD);
677cad46a33SMatthew Brost GEM_WARN_ON(atomic_read(&guc->outstanding_submission_g2h));
6780f261b24SDaniele Ceraolo Spurio
6790f261b24SDaniele Ceraolo Spurio guc_disable_communication(guc);
6800f261b24SDaniele Ceraolo Spurio }
6810f261b24SDaniele Ceraolo Spurio
intel_uc_suspend(struct intel_uc * uc)682ca7b2c1bSDaniele Ceraolo Spurio void intel_uc_suspend(struct intel_uc *uc)
6830f261b24SDaniele Ceraolo Spurio {
684ca7b2c1bSDaniele Ceraolo Spurio struct intel_guc *guc = &uc->guc;
6850f261b24SDaniele Ceraolo Spurio intel_wakeref_t wakeref;
686cad46a33SMatthew Brost int err;
6870f261b24SDaniele Ceraolo Spurio
68815bd4a67SDaniele Ceraolo Spurio /* flush the GSC worker */
689b09f9670SDaniele Ceraolo Spurio intel_gsc_uc_flush_work(&uc->gsc);
69015bd4a67SDaniele Ceraolo Spurio
691a187f13dSDaniele Ceraolo Spurio if (!intel_guc_is_ready(guc)) {
692a187f13dSDaniele Ceraolo Spurio guc->interrupts.enabled = false;
6930f261b24SDaniele Ceraolo Spurio return;
694a187f13dSDaniele Ceraolo Spurio }
6950f261b24SDaniele Ceraolo Spurio
696cad46a33SMatthew Brost with_intel_runtime_pm(&uc_to_gt(uc)->i915->runtime_pm, wakeref) {
697cad46a33SMatthew Brost err = intel_guc_suspend(guc);
698cad46a33SMatthew Brost if (err)
6992f8c06cbSMichal Wajdeczko guc_dbg(guc, "Failed to suspend, %pe", ERR_PTR(err));
700cad46a33SMatthew Brost }
7010f261b24SDaniele Ceraolo Spurio }
7020f261b24SDaniele Ceraolo Spurio
__uc_resume_mappings(struct intel_uc * uc)7033532e75dSDaniele Ceraolo Spurio static void __uc_resume_mappings(struct intel_uc *uc)
7043532e75dSDaniele Ceraolo Spurio {
7053532e75dSDaniele Ceraolo Spurio intel_uc_fw_resume_mapping(&uc->guc.fw);
7063532e75dSDaniele Ceraolo Spurio intel_uc_fw_resume_mapping(&uc->huc.fw);
7073532e75dSDaniele Ceraolo Spurio }
7083532e75dSDaniele Ceraolo Spurio
__uc_resume(struct intel_uc * uc,bool enable_communication)709602776f9SDaniele Ceraolo Spurio static int __uc_resume(struct intel_uc *uc, bool enable_communication)
7100f261b24SDaniele Ceraolo Spurio {
711ca7b2c1bSDaniele Ceraolo Spurio struct intel_guc *guc = &uc->guc;
712899a0fd7SVinay Belgaumkar struct intel_gt *gt = guc_to_gt(guc);
7130f261b24SDaniele Ceraolo Spurio int err;
7140f261b24SDaniele Ceraolo Spurio
715e85de177SMichal Wajdeczko if (!intel_guc_is_fw_running(guc))
7160f261b24SDaniele Ceraolo Spurio return 0;
7170f261b24SDaniele Ceraolo Spurio
718602776f9SDaniele Ceraolo Spurio /* Make sure we enable communication if and only if it's disabled */
7195db18567SDaniele Ceraolo Spurio GEM_BUG_ON(enable_communication == intel_guc_ct_enabled(&guc->ct));
720602776f9SDaniele Ceraolo Spurio
721602776f9SDaniele Ceraolo Spurio if (enable_communication)
7220f261b24SDaniele Ceraolo Spurio guc_enable_communication(guc);
7230f261b24SDaniele Ceraolo Spurio
724899a0fd7SVinay Belgaumkar /* If we are only resuming GuC communication but not reloading
725899a0fd7SVinay Belgaumkar * GuC, we need to ensure the ARAT timer interrupt is enabled
726899a0fd7SVinay Belgaumkar * again. In case of GuC reload, it is enabled during SLPC enable.
727899a0fd7SVinay Belgaumkar */
728899a0fd7SVinay Belgaumkar if (enable_communication && intel_uc_uses_guc_slpc(uc))
729899a0fd7SVinay Belgaumkar intel_guc_pm_intrmsk_enable(gt);
730899a0fd7SVinay Belgaumkar
7310f261b24SDaniele Ceraolo Spurio err = intel_guc_resume(guc);
7320f261b24SDaniele Ceraolo Spurio if (err) {
7332f8c06cbSMichal Wajdeczko guc_dbg(guc, "Failed to resume, %pe", ERR_PTR(err));
7340f261b24SDaniele Ceraolo Spurio return err;
7350f261b24SDaniele Ceraolo Spurio }
7360f261b24SDaniele Ceraolo Spurio
737913e013eSDaniele Ceraolo Spurio intel_gsc_uc_resume(&uc->gsc);
738913e013eSDaniele Ceraolo Spurio
7390f261b24SDaniele Ceraolo Spurio return 0;
7400f261b24SDaniele Ceraolo Spurio }
741602776f9SDaniele Ceraolo Spurio
intel_uc_resume(struct intel_uc * uc)742602776f9SDaniele Ceraolo Spurio int intel_uc_resume(struct intel_uc *uc)
743602776f9SDaniele Ceraolo Spurio {
744602776f9SDaniele Ceraolo Spurio /*
745602776f9SDaniele Ceraolo Spurio * When coming out of S3/S4 we sanitize and re-init the HW, so
746602776f9SDaniele Ceraolo Spurio * communication is already re-enabled at this point.
747602776f9SDaniele Ceraolo Spurio */
748602776f9SDaniele Ceraolo Spurio return __uc_resume(uc, false);
749602776f9SDaniele Ceraolo Spurio }
750602776f9SDaniele Ceraolo Spurio
intel_uc_runtime_resume(struct intel_uc * uc)751602776f9SDaniele Ceraolo Spurio int intel_uc_runtime_resume(struct intel_uc *uc)
752602776f9SDaniele Ceraolo Spurio {
753602776f9SDaniele Ceraolo Spurio /*
754602776f9SDaniele Ceraolo Spurio * During runtime resume we don't sanitize, so we need to re-init
755602776f9SDaniele Ceraolo Spurio * communication as well.
756602776f9SDaniele Ceraolo Spurio */
757602776f9SDaniele Ceraolo Spurio return __uc_resume(uc, true);
758602776f9SDaniele Ceraolo Spurio }
7596fbeda0bSMichal Wajdeczko
7606fbeda0bSMichal Wajdeczko static const struct intel_uc_ops uc_ops_off = {
7616fbeda0bSMichal Wajdeczko .init_hw = __uc_check_hw,
76202224691SDaniele Ceraolo Spurio .fini = __uc_fini, /* to clean-up the init_early initialization */
7636fbeda0bSMichal Wajdeczko };
7646fbeda0bSMichal Wajdeczko
7656fbeda0bSMichal Wajdeczko static const struct intel_uc_ops uc_ops_on = {
7661868c757SMichal Wajdeczko .sanitize = __uc_sanitize,
7671868c757SMichal Wajdeczko
76839ddb863SMichal Wajdeczko .init_fw = __uc_fetch_firmwares,
76939ddb863SMichal Wajdeczko .fini_fw = __uc_cleanup_firmwares,
77039ddb863SMichal Wajdeczko
771cc93f7b0SMichal Wajdeczko .init = __uc_init,
772cc93f7b0SMichal Wajdeczko .fini = __uc_fini,
773cc93f7b0SMichal Wajdeczko
7746fbeda0bSMichal Wajdeczko .init_hw = __uc_init_hw,
7756fbeda0bSMichal Wajdeczko .fini_hw = __uc_fini_hw,
7763532e75dSDaniele Ceraolo Spurio
7773532e75dSDaniele Ceraolo Spurio .resume_mappings = __uc_resume_mappings,
7786fbeda0bSMichal Wajdeczko };
779