summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/pxp/intel_pxp.c
diff options
context:
space:
mode:
authorHuang, Sean Z <sean.z.huang@intel.com>2021-09-24 21:14:44 +0200
committerRodrigo Vivi <rodrigo.vivi@intel.com>2021-10-04 19:10:55 +0200
commit2ae096872a2c61da476fb072348ef8f07ea54c9b (patch)
treebbc04d07855df5511fbd25278e15335405516c18 /drivers/gpu/drm/i915/pxp/intel_pxp.c
parentdrm/i915/pxp: Implement arb session teardown (diff)
downloadlinux-2ae096872a2c61da476fb072348ef8f07ea54c9b.tar.xz
linux-2ae096872a2c61da476fb072348ef8f07ea54c9b.zip
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: Alan Previn <alan.previn.teres.alexis@intel.com> 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-10-alan.previn.teres.alexis@intel.com
Diffstat (limited to 'drivers/gpu/drm/i915/pxp/intel_pxp.c')
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp.c66
1 files changed, 60 insertions, 6 deletions
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp.c b/drivers/gpu/drm/i915/pxp/intel_pxp.c
index 6afa87f90eef..2e188217c3b7 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp.c
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp.c
@@ -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);
}