Skip to content

Commit

Permalink
drm/i915/pxp: Enable PXP power management
Browse files Browse the repository at this point in the history
During the power event S3+ sleep/resume, hardware will lose all the
encryption keys for every hardware session, even though the
session state might still be marked as alive after resume. Therefore,
we should consider the session as dead on suspend and invalidate all the
objects. The session will be automatically restarted on the first
protected submission on resume.

v2: runtime suspend also invalidates the keys
v3: fix return codes, simplify rpm ops (Chris), use the new worker func
v4: invalidate the objects on suspend, don't re-create the arb sesson on
resume (delayed to first submission).
v5: move irq changes back to irq patch (Rodrigo)
v6: drop invalidation in runtime suspend (Rodrigo)

Signed-off-by: Huang, Sean Z <sean.z.huang@intel.com>
Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20210924191452.1539378-13-alan.previn.teres.alexis@intel.com
  • Loading branch information
Huang, Sean Z authored and Rodrigo Vivi committed Oct 4, 2021
1 parent 32271ec commit 0cfab4c
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 11 deletions.
1 change: 1 addition & 0 deletions drivers/gpu/drm/i915/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ i915-$(CONFIG_DRM_I915_PXP) += \
pxp/intel_pxp.o \
pxp/intel_pxp_cmd.o \
pxp/intel_pxp_irq.o \
pxp/intel_pxp_pm.o \
pxp/intel_pxp_session.o \
pxp/intel_pxp_tee.o

Expand Down
16 changes: 15 additions & 1 deletion drivers/gpu/drm/i915/gt/intel_gt_pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "intel_rc6.h"
#include "intel_rps.h"
#include "intel_wakeref.h"
#include "pxp/intel_pxp_pm.h"

#define I915_GT_SUSPEND_IDLE_TIMEOUT (HZ / 2)

Expand Down Expand Up @@ -264,6 +265,8 @@ int intel_gt_resume(struct intel_gt *gt)

intel_uc_resume(&gt->uc);

intel_pxp_resume(&gt->pxp);

user_forcewake(gt, false);

out_fw:
Expand Down Expand Up @@ -297,6 +300,8 @@ void intel_gt_suspend_prepare(struct intel_gt *gt)
{
user_forcewake(gt, true);
wait_for_suspend(gt);

intel_pxp_suspend(&gt->pxp, false);
}

static suspend_state_t pm_suspend_target(void)
Expand Down Expand Up @@ -348,18 +353,27 @@ void intel_gt_suspend_late(struct intel_gt *gt)

void intel_gt_runtime_suspend(struct intel_gt *gt)
{
intel_pxp_suspend(&gt->pxp, true);
intel_uc_runtime_suspend(&gt->uc);

GT_TRACE(gt, "\n");
}

int intel_gt_runtime_resume(struct intel_gt *gt)
{
int ret;

GT_TRACE(gt, "\n");
intel_gt_init_swizzling(gt);
intel_ggtt_restore_fences(gt->ggtt);

return intel_uc_runtime_resume(&gt->uc);
ret = intel_uc_runtime_resume(&gt->uc);
if (ret)
return ret;

intel_pxp_resume(&gt->pxp);

return 0;
}

static ktime_t __intel_gt_get_awake_time(const struct intel_gt *gt)
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/i915/i915_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@
#include "gt/intel_gt_pm.h"
#include "gt/intel_rc6.h"

#include "pxp/intel_pxp_pm.h"

#include "i915_debugfs.h"
#include "i915_drv.h"
#include "i915_ioc32.h"
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/i915/pxp/intel_pxp_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "gt/intel_gt_types.h"
#include "i915_irq.h"
#include "i915_reg.h"
#include "intel_runtime_pm.h"

/**
* intel_pxp_irq_handler - Handles PXP interrupts.
Expand Down
46 changes: 46 additions & 0 deletions drivers/gpu/drm/i915/pxp/intel_pxp_pm.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// SPDX-License-Identifier: MIT
/*
* Copyright(c) 2020 Intel Corporation.
*/

#include "intel_pxp.h"
#include "intel_pxp_irq.h"
#include "intel_pxp_pm.h"
#include "intel_pxp_session.h"

void intel_pxp_suspend(struct intel_pxp *pxp, bool runtime)
{
if (!intel_pxp_is_enabled(pxp))
return;

pxp->arb_is_valid = false;

/*
* Contexts using protected objects keep a runtime PM reference, so we
* can only runtime suspend when all of them have been either closed
* or banned. Therefore, there is no need to invalidate in that
* scenario.
*/
if (!runtime)
intel_pxp_invalidate(pxp);

intel_pxp_fini_hw(pxp);

pxp->hw_state_invalidated = false;
}

void intel_pxp_resume(struct intel_pxp *pxp)
{
if (!intel_pxp_is_enabled(pxp))
return;

/*
* The PXP component gets automatically unbound when we go into S3 and
* re-bound after we come out, so in that scenario we can defer the
* hw init to the bind call.
*/
if (!pxp->pxp_component)
return;

intel_pxp_init_hw(pxp);
}
24 changes: 24 additions & 0 deletions drivers/gpu/drm/i915/pxp/intel_pxp_pm.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright(c) 2020, Intel Corporation. All rights reserved.
*/

#ifndef __INTEL_PXP_PM_H__
#define __INTEL_PXP_PM_H__

#include "intel_pxp_types.h"

#ifdef CONFIG_DRM_I915_PXP
void intel_pxp_suspend(struct intel_pxp *pxp, bool runtime);
void intel_pxp_resume(struct intel_pxp *pxp);
#else
static inline void intel_pxp_suspend(struct intel_pxp *pxp, bool runtime)
{
}

static inline void intel_pxp_resume(struct intel_pxp *pxp)
{
}
#endif

#endif /* __INTEL_PXP_PM_H__ */
38 changes: 28 additions & 10 deletions drivers/gpu/drm/i915/pxp/intel_pxp_session.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,29 +21,36 @@

static bool intel_pxp_session_is_in_play(struct intel_pxp *pxp, u32 id)
{
struct intel_gt *gt = pxp_to_gt(pxp);
struct intel_uncore *uncore = pxp_to_gt(pxp)->uncore;
intel_wakeref_t wakeref;
u32 sip = 0;

with_intel_runtime_pm(gt->uncore->rpm, wakeref)
sip = intel_uncore_read(gt->uncore, GEN12_KCR_SIP);
/* if we're suspended the session is considered off */
with_intel_runtime_pm_if_in_use(uncore->rpm, wakeref)
sip = intel_uncore_read(uncore, GEN12_KCR_SIP);

return sip & BIT(id);
}

static int pxp_wait_for_session_state(struct intel_pxp *pxp, u32 id, bool in_play)
{
struct intel_gt *gt = pxp_to_gt(pxp);
struct intel_uncore *uncore = pxp_to_gt(pxp)->uncore;
intel_wakeref_t wakeref;
u32 mask = BIT(id);
int ret;

with_intel_runtime_pm(gt->uncore->rpm, wakeref)
ret = intel_wait_for_register(gt->uncore,
GEN12_KCR_SIP,
mask,
in_play ? mask : 0,
100);
/* if we're suspended the session is considered off */
wakeref = intel_runtime_pm_get_if_in_use(uncore->rpm);
if (!wakeref)
return in_play ? -ENODEV : 0;

ret = intel_wait_for_register(uncore,
GEN12_KCR_SIP,
mask,
in_play ? mask : 0,
100);

intel_runtime_pm_put(uncore->rpm, wakeref);

return ret;
}
Expand Down Expand Up @@ -135,6 +142,7 @@ void intel_pxp_session_work(struct work_struct *work)
{
struct intel_pxp *pxp = container_of(work, typeof(*pxp), session_work);
struct intel_gt *gt = pxp_to_gt(pxp);
intel_wakeref_t wakeref;
u32 events = 0;

spin_lock_irq(&gt->irq_lock);
Expand All @@ -147,11 +155,21 @@ void intel_pxp_session_work(struct work_struct *work)
if (events & PXP_INVAL_REQUIRED)
intel_pxp_invalidate(pxp);

/*
* If we're processing an event while suspending then don't bother,
* we're going to re-init everything on resume anyway.
*/
wakeref = intel_runtime_pm_get_if_in_use(gt->uncore->rpm);
if (!wakeref)
return;

if (events & PXP_TERMINATION_REQUEST) {
events &= ~PXP_TERMINATION_COMPLETE;
pxp_terminate(pxp);
}

if (events & PXP_TERMINATION_COMPLETE)
pxp_terminate_complete(pxp);

intel_runtime_pm_put(gt->uncore->rpm, wakeref);
}
9 changes: 9 additions & 0 deletions drivers/gpu/drm/i915/pxp/intel_pxp_tee.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,16 +78,25 @@ static int intel_pxp_tee_io_message(struct intel_pxp *pxp,
static int i915_pxp_tee_component_bind(struct device *i915_kdev,
struct device *tee_kdev, void *data)
{
struct drm_i915_private *i915 = kdev_to_i915(i915_kdev);
struct intel_pxp *pxp = i915_dev_to_pxp(i915_kdev);
intel_wakeref_t wakeref;

mutex_lock(&pxp->tee_mutex);
pxp->pxp_component = data;
pxp->pxp_component->tee_dev = tee_kdev;
mutex_unlock(&pxp->tee_mutex);

/* if we are suspended, the HW will be re-initialized on resume */
wakeref = intel_runtime_pm_get_if_in_use(&i915->runtime_pm);
if (!wakeref)
return 0;

/* the component is required to fully start the PXP HW */
intel_pxp_init_hw(pxp);

intel_runtime_pm_put(&i915->runtime_pm, wakeref);

return 0;
}

Expand Down

0 comments on commit 0cfab4c

Please sign in to comment.