diff options
author | Huang, Sean Z <sean.z.huang@intel.com> | 2021-09-24 21:14:44 +0200 |
---|---|---|
committer | Rodrigo Vivi <rodrigo.vivi@intel.com> | 2021-10-04 19:10:55 +0200 |
commit | 2ae096872a2c61da476fb072348ef8f07ea54c9b (patch) | |
tree | bbc04d07855df5511fbd25278e15335405516c18 /drivers/gpu/drm/i915/pxp/intel_pxp.c | |
parent | drm/i915/pxp: Implement arb session teardown (diff) | |
download | linux-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.c | 66 |
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(>->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(>->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); } |