diff options
Diffstat (limited to 'drivers/gpu/drm/i915/pxp/intel_pxp.c')
| -rw-r--r-- | drivers/gpu/drm/i915/pxp/intel_pxp.c | 166 |
1 files changed, 131 insertions, 35 deletions
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp.c b/drivers/gpu/drm/i915/pxp/intel_pxp.c index 9d4c7724e98e..d4b0c76f335b 100644 --- a/drivers/gpu/drm/i915/pxp/intel_pxp.c +++ b/drivers/gpu/drm/i915/pxp/intel_pxp.c @@ -2,17 +2,21 @@ /* * Copyright(c) 2020 Intel Corporation. */ + #include <linux/workqueue.h> -#include "gem/i915_gem_context.h" +#include <drm/drm_print.h> +#include "gem/i915_gem_context.h" #include "gt/intel_context.h" #include "gt/intel_gt.h" #include "i915_drv.h" - +#include "i915_wait_util.h" #include "intel_pxp.h" +#include "intel_pxp_gsccs.h" #include "intel_pxp_irq.h" +#include "intel_pxp_regs.h" #include "intel_pxp_session.h" #include "intel_pxp_tee.h" #include "intel_pxp_types.h" @@ -60,21 +64,22 @@ bool intel_pxp_is_active(const struct intel_pxp *pxp) return IS_ENABLED(CONFIG_DRM_I915_PXP) && pxp && pxp->arb_is_valid; } -/* KCR register definitions */ -#define KCR_INIT _MMIO(0x320f0) -/* Setting KCR Init bit is required after system boot */ -#define KCR_INIT_ALLOW_DISPLAY_ME_WRITES REG_BIT(14) +static void kcr_pxp_set_status(const struct intel_pxp *pxp, bool enable) +{ + u32 val = enable ? _MASKED_BIT_ENABLE(KCR_INIT_ALLOW_DISPLAY_ME_WRITES) : + _MASKED_BIT_DISABLE(KCR_INIT_ALLOW_DISPLAY_ME_WRITES); + + intel_uncore_write(pxp->ctrl_gt->uncore, KCR_INIT(pxp->kcr_base), val); +} -static void kcr_pxp_enable(struct intel_gt *gt) +static void kcr_pxp_enable(const struct intel_pxp *pxp) { - intel_uncore_write(gt->uncore, KCR_INIT, - _MASKED_BIT_ENABLE(KCR_INIT_ALLOW_DISPLAY_ME_WRITES)); + kcr_pxp_set_status(pxp, true); } -static void kcr_pxp_disable(struct intel_gt *gt) +static void kcr_pxp_disable(const struct intel_pxp *pxp) { - intel_uncore_write(gt->uncore, KCR_INIT, - _MASKED_BIT_DISABLE(KCR_INIT_ALLOW_DISPLAY_ME_WRITES)); + kcr_pxp_set_status(pxp, false); } static int create_vcs_context(struct intel_pxp *pxp) @@ -126,13 +131,21 @@ static void pxp_init_full(struct intel_pxp *pxp) init_completion(&pxp->termination); complete_all(&pxp->termination); + if (pxp->ctrl_gt->type == GT_MEDIA) + pxp->kcr_base = MTL_KCR_BASE; + else + pxp->kcr_base = GEN12_KCR_BASE; + intel_pxp_session_management_init(pxp); ret = create_vcs_context(pxp); if (ret) return; - ret = intel_pxp_tee_component_init(pxp); + if (HAS_ENGINE(pxp->ctrl_gt, GSC0)) + ret = intel_pxp_gsccs_init(pxp); + else + ret = intel_pxp_tee_component_init(pxp); if (ret) goto out_context; @@ -151,31 +164,34 @@ static struct intel_gt *find_gt_for_required_teelink(struct drm_i915_private *i9 * for HuC authentication. For now, its limited to DG2. */ if (IS_ENABLED(CONFIG_INTEL_MEI_PXP) && IS_ENABLED(CONFIG_INTEL_MEI_GSC) && - intel_huc_is_loaded_by_gsc(&i915->gt0.uc.huc) && intel_uc_uses_huc(&i915->gt0.uc)) - return &i915->gt0; + intel_huc_is_loaded_by_gsc(&to_gt(i915)->uc.huc) && intel_uc_uses_huc(&to_gt(i915)->uc)) + return to_gt(i915); return NULL; } static struct intel_gt *find_gt_for_required_protected_content(struct drm_i915_private *i915) { - if (!IS_ENABLED(CONFIG_DRM_I915_PXP) || !INTEL_INFO(i915)->has_pxp) + if (!HAS_PXP(i915)) return NULL; /* * For MTL onwards, PXP-controller-GT needs to have a valid GSC engine * on the media GT. NOTE: if we have a media-tile with a GSC-engine, - * the VDBOX is already present so skip that check + * the VDBOX is already present so skip that check. We also have to + * ensure the GSC and HUC firmware are coming online */ - if (i915->media_gt && HAS_ENGINE(i915->media_gt, GSC0)) + if (i915->media_gt && HAS_ENGINE(i915->media_gt, GSC0) && + intel_uc_fw_is_loadable(&i915->media_gt->uc.gsc.fw) && + intel_uc_fw_is_loadable(&i915->media_gt->uc.huc.fw)) return i915->media_gt; /* * Else we rely on mei-pxp module but only on legacy platforms * prior to having separate media GTs and has a valid VDBOX. */ - if (IS_ENABLED(CONFIG_INTEL_MEI_PXP) && !i915->media_gt && VDBOX_MASK(&i915->gt0)) - return &i915->gt0; + if (IS_ENABLED(CONFIG_INTEL_MEI_PXP) && !i915->media_gt && VDBOX_MASK(to_gt(i915))) + return to_gt(i915); return NULL; } @@ -185,6 +201,9 @@ int intel_pxp_init(struct drm_i915_private *i915) struct intel_gt *gt; bool is_full_feature = false; + if (intel_gt_is_wedged(to_gt(i915))) + return -ENOTCONN; + /* * NOTE: Get the ctrl_gt before checking intel_pxp_is_supported since * we still need it if PXP's backend tee transport is needed. @@ -207,7 +226,9 @@ int intel_pxp_init(struct drm_i915_private *i915) if (!i915->pxp) return -ENOMEM; + /* init common info used by all feature-mode usages*/ i915->pxp->ctrl_gt = gt; + mutex_init(&i915->pxp->tee_mutex); /* * If full PXP feature is not available but HuC is loaded by GSC on pre-MTL @@ -229,7 +250,10 @@ void intel_pxp_fini(struct drm_i915_private *i915) i915->pxp->arb_is_valid = false; - intel_pxp_tee_component_fini(i915->pxp); + if (HAS_ENGINE(i915->pxp->ctrl_gt, GSC0)) + intel_pxp_gsccs_fini(i915->pxp); + else + intel_pxp_tee_component_fini(i915->pxp); destroy_vcs_context(i915->pxp); @@ -270,10 +294,22 @@ static bool pxp_component_bound(struct intel_pxp *pxp) return bound; } +int intel_pxp_get_backend_timeout_ms(struct intel_pxp *pxp) +{ + if (HAS_ENGINE(pxp->ctrl_gt, GSC0)) + return GSCFW_MAX_ROUND_TRIP_LATENCY_MS; + else + return 250; +} + static int __pxp_global_teardown_final(struct intel_pxp *pxp) { + int timeout; + if (!pxp->arb_is_valid) return 0; + + drm_dbg(&pxp->ctrl_gt->i915->drm, "PXP: teardown for suspend/fini"); /* * To ensure synchronous and coherent session teardown completion * in response to suspend or shutdown triggers, don't use a worker. @@ -281,7 +317,9 @@ static int __pxp_global_teardown_final(struct intel_pxp *pxp) intel_pxp_mark_termination_in_progress(pxp); intel_pxp_terminate(pxp, false); - if (!wait_for_completion_timeout(&pxp->termination, msecs_to_jiffies(250))) + timeout = intel_pxp_get_backend_timeout_ms(pxp); + + if (!wait_for_completion_timeout(&pxp->termination, msecs_to_jiffies(timeout))) return -ETIMEDOUT; return 0; @@ -289,16 +327,25 @@ static int __pxp_global_teardown_final(struct intel_pxp *pxp) static int __pxp_global_teardown_restart(struct intel_pxp *pxp) { + int timeout; + if (pxp->arb_is_valid) return 0; + + drm_dbg(&pxp->ctrl_gt->i915->drm, "PXP: teardown for restart"); /* * The arb-session is currently inactive and we are doing a reset and restart * due to a runtime event. Use the worker that was designed for this. */ pxp_queue_termination(pxp); - if (!wait_for_completion_timeout(&pxp->termination, msecs_to_jiffies(250))) + timeout = intel_pxp_get_backend_timeout_ms(pxp); + + if (!wait_for_completion_timeout(&pxp->termination, msecs_to_jiffies(timeout))) { + drm_dbg(&pxp->ctrl_gt->i915->drm, "PXP: restart backend timed out (%d ms)", + timeout); return -ETIMEDOUT; + } return 0; } @@ -324,19 +371,67 @@ void intel_pxp_end(struct intel_pxp *pxp) intel_runtime_pm_put(&i915->runtime_pm, wakeref); } +static bool pxp_required_fw_failed(struct intel_pxp *pxp) +{ + if (__intel_uc_fw_status(&pxp->ctrl_gt->uc.huc.fw) == INTEL_UC_FIRMWARE_LOAD_FAIL) + return true; + if (HAS_ENGINE(pxp->ctrl_gt, GSC0) && + __intel_uc_fw_status(&pxp->ctrl_gt->uc.gsc.fw) == INTEL_UC_FIRMWARE_LOAD_FAIL) + return true; + + return false; +} + +static bool pxp_fw_dependencies_completed(struct intel_pxp *pxp) +{ + if (HAS_ENGINE(pxp->ctrl_gt, GSC0)) + return intel_pxp_gsccs_is_ready_for_sessions(pxp); + + return pxp_component_bound(pxp); +} + +/* + * this helper is used by both intel_pxp_start and by + * the GET_PARAM IOCTL that user space calls. Thus, the + * return values here should match the UAPI spec. + */ +int intel_pxp_get_readiness_status(struct intel_pxp *pxp, int timeout_ms) +{ + if (!intel_pxp_is_enabled(pxp)) + return -ENODEV; + + if (pxp_required_fw_failed(pxp)) + return -ENODEV; + + if (pxp->platform_cfg_is_bad) + return -ENODEV; + + if (timeout_ms) { + if (wait_for(pxp_fw_dependencies_completed(pxp), timeout_ms)) + return 2; + } else if (!pxp_fw_dependencies_completed(pxp)) { + return 2; + } + return 1; +} + /* * the arb session is restarted from the irq work when we receive the * termination completion interrupt */ +#define PXP_READINESS_TIMEOUT 250 + int intel_pxp_start(struct intel_pxp *pxp) { int ret = 0; - if (!intel_pxp_is_enabled(pxp)) - return -ENODEV; - - if (wait_for(pxp_component_bound(pxp), 250)) - return -ENXIO; + ret = intel_pxp_get_readiness_status(pxp, PXP_READINESS_TIMEOUT); + if (ret < 0) { + drm_dbg(&pxp->ctrl_gt->i915->drm, "PXP: tried but not-avail (%d)", ret); + return ret; + } else if (ret > 1) { + return -EIO; /* per UAPI spec, user may retry later */ + } mutex_lock(&pxp->arb_mutex); @@ -357,21 +452,22 @@ unlock: void intel_pxp_init_hw(struct intel_pxp *pxp) { - kcr_pxp_enable(pxp->ctrl_gt); + kcr_pxp_enable(pxp); intel_pxp_irq_enable(pxp); } void intel_pxp_fini_hw(struct intel_pxp *pxp) { - kcr_pxp_disable(pxp->ctrl_gt); - + kcr_pxp_disable(pxp); intel_pxp_irq_disable(pxp); } -int intel_pxp_key_check(struct intel_pxp *pxp, - struct drm_i915_gem_object *obj, - bool assign) +int intel_pxp_key_check(struct drm_gem_object *_obj, bool assign) { + struct drm_i915_gem_object *obj = to_intel_bo(_obj); + struct drm_i915_private *i915 = to_i915(_obj->dev); + struct intel_pxp *pxp = i915->pxp; + if (!intel_pxp_is_active(pxp)) return -ENODEV; @@ -437,7 +533,7 @@ void intel_pxp_invalidate(struct intel_pxp *pxp) if (ctx->pxp_wakeref) { intel_runtime_pm_put(&i915->runtime_pm, ctx->pxp_wakeref); - ctx->pxp_wakeref = 0; + ctx->pxp_wakeref = NULL; } spin_lock_irq(&i915->gem.contexts.lock); |
