Commit 2ae09687 authored by Huang, Sean Z's avatar Huang, Sean Z Committed by Rodrigo Vivi
Browse files

drm/i915/pxp: Implement PXP irq handler



The HW will generate a teardown interrupt when session termination is
required, which requires i915 to submit a terminating batch. Once the HW
is done with the termination it will generate another interrupt, at
which point it is safe to re-create the session.

Since the termination and re-creation flow is something we want to
trigger from the driver as well, use a common work function that can be
called both from the irq handler and from the driver set-up flows, which
has the addded benefit of allowing us to skip any extra locks because
the work itself serializes the operations.

v2: use struct completion instead of bool (Chris)
v3: drop locks, clean up functions and improve comments (Chris),
    move to common work function.
v4: improve comments, simplify wait logic (Rodrigo)
v5: unconditionally set interrupts, rename state_attacked var (Rodrigo)
v10: remove inclusion of intel_gt_types.h from intel_pxp.h (Jani)

Signed-off-by: default avatarAlan Previn <alan.previn.teres.alexis@intel.com>
Signed-off-by: default avatarHuang, Sean Z <sean.z.huang@intel.com>
Signed-off-by: default avatarDaniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Reviewed-by: default avatarRodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: default avatarRodrigo Vivi <rodrigo.vivi@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20210924191452.1539378-10-alan.previn.teres.alexis@intel.com
parent 95c9e122
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -282,6 +282,7 @@ i915-y += i915_perf.o
i915-$(CONFIG_DRM_I915_PXP) += \
	pxp/intel_pxp.o \
	pxp/intel_pxp_cmd.o \
	pxp/intel_pxp_irq.o \
	pxp/intel_pxp_session.o \
	pxp/intel_pxp_tee.o

+7 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
#include "intel_lrc_reg.h"
#include "intel_uncore.h"
#include "intel_rps.h"
#include "pxp/intel_pxp_irq.h"

static void guc_irq_handler(struct intel_guc *guc, u16 iir)
{
@@ -64,6 +65,9 @@ gen11_other_irq_handler(struct intel_gt *gt, const u8 instance,
	if (instance == OTHER_GTPM_INSTANCE)
		return gen11_rps_irq_handler(&gt->rps, iir);

	if (instance == OTHER_KCR_INSTANCE)
		return intel_pxp_irq_handler(&gt->pxp, iir);

	WARN_ONCE(1, "unhandled other interrupt instance=0x%x, iir=0x%x\n",
		  instance, iir);
}
@@ -196,6 +200,9 @@ void gen11_gt_irq_reset(struct intel_gt *gt)
	intel_uncore_write(uncore, GEN11_GPM_WGBOXPERF_INTR_MASK,  ~0);
	intel_uncore_write(uncore, GEN11_GUC_SG_INTR_ENABLE, 0);
	intel_uncore_write(uncore, GEN11_GUC_SG_INTR_MASK,  ~0);

	intel_uncore_write(uncore, GEN11_CRYPTO_RSVD_INTR_ENABLE, 0);
	intel_uncore_write(uncore, GEN11_CRYPTO_RSVD_INTR_MASK,  ~0);
}

void gen11_gt_irq_postinstall(struct intel_gt *gt)
+1 −0
Original line number Diff line number Diff line
@@ -8124,6 +8124,7 @@ enum {
/* irq instances for OTHER_CLASS */
#define OTHER_GUC_INSTANCE	0
#define OTHER_GTPM_INSTANCE	1
#define OTHER_KCR_INSTANCE	4

#define GEN11_INTR_IDENTITY_REG(x)	_MMIO(0x190060 + ((x) * 4))

+60 −6
Original line number Diff line number Diff line
@@ -2,7 +2,9 @@
/*
 * Copyright(c) 2020 Intel Corporation.
 */
#include <linux/workqueue.h>
#include "intel_pxp.h"
#include "intel_pxp_irq.h"
#include "intel_pxp_session.h"
#include "intel_pxp_tee.h"
#include "gt/intel_context.h"
@@ -80,6 +82,16 @@ void intel_pxp_init(struct intel_pxp *pxp)

	mutex_init(&pxp->tee_mutex);

	/*
	 * we'll use the completion to check if there is a termination pending,
	 * so we start it as completed and we reinit it when a termination
	 * is triggered.
	 */
	init_completion(&pxp->termination);
	complete_all(&pxp->termination);

	INIT_WORK(&pxp->session_work, intel_pxp_session_work);

	ret = create_vcs_context(pxp);
	if (ret)
		return;
@@ -108,19 +120,61 @@ void intel_pxp_fini(struct intel_pxp *pxp)
	destroy_vcs_context(pxp);
}

void intel_pxp_init_hw(struct intel_pxp *pxp)
void intel_pxp_mark_termination_in_progress(struct intel_pxp *pxp)
{
	int ret;
	pxp->arb_is_valid = false;
	reinit_completion(&pxp->termination);
}

static void intel_pxp_queue_termination(struct intel_pxp *pxp)
{
	struct intel_gt *gt = pxp_to_gt(pxp);

	/*
	 * We want to get the same effect as if we received a termination
	 * interrupt, so just pretend that we did.
	 */
	spin_lock_irq(&gt->irq_lock);
	intel_pxp_mark_termination_in_progress(pxp);
	pxp->session_events |= PXP_TERMINATION_REQUEST;
	queue_work(system_unbound_wq, &pxp->session_work);
	spin_unlock_irq(&gt->irq_lock);
}

/*
 * the arb session is restarted from the irq work when we receive the
 * termination completion interrupt
 */
int intel_pxp_wait_for_arb_start(struct intel_pxp *pxp)
{
	if (!intel_pxp_is_enabled(pxp))
		return 0;

	if (!wait_for_completion_timeout(&pxp->termination,
					 msecs_to_jiffies(100)))
		return -ETIMEDOUT;

	if (!pxp->arb_is_valid)
		return -EIO;

	return 0;
}

void intel_pxp_init_hw(struct intel_pxp *pxp)
{
	kcr_pxp_enable(pxp_to_gt(pxp));
	intel_pxp_irq_enable(pxp);

	/* always emit a full termination to clean the state */
	ret = intel_pxp_terminate_arb_session_and_global(pxp);
	if (!ret)
		intel_pxp_create_arb_session(pxp);
	/*
	 * the session could've been attacked while we weren't loaded, so
	 * handle it as if it was and re-create it.
	 */
	intel_pxp_queue_termination(pxp);
}

void intel_pxp_fini_hw(struct intel_pxp *pxp)
{
	kcr_pxp_disable(pxp_to_gt(pxp));

	intel_pxp_irq_disable(pxp);
}
+8 −0
Original line number Diff line number Diff line
@@ -22,6 +22,9 @@ void intel_pxp_fini(struct intel_pxp *pxp);

void intel_pxp_init_hw(struct intel_pxp *pxp);
void intel_pxp_fini_hw(struct intel_pxp *pxp);

void intel_pxp_mark_termination_in_progress(struct intel_pxp *pxp);
int intel_pxp_wait_for_arb_start(struct intel_pxp *pxp);
#else
static inline void intel_pxp_init(struct intel_pxp *pxp)
{
@@ -30,6 +33,11 @@ static inline void intel_pxp_init(struct intel_pxp *pxp)
static inline void intel_pxp_fini(struct intel_pxp *pxp)
{
}

static inline int intel_pxp_wait_for_arb_start(struct intel_pxp *pxp)
{
	return -ENODEV;
}
#endif

#endif /* __INTEL_PXP_H__ */
Loading