This is a huge, chaotic mass of registers copied over as-is without any real cleanup. We'll come back and organize these better, align on consistent coding style, remove dead code, etc. in separate patches later that will be easier to review. v2: - Add missing include in intel_pxp_irq.c v3: - Correct a few indentation errors (Lucas) - Minor conflict resolution Cc: Jani Nikula <jani.nikula@intel.com> Signed-off-by: Matt Roper <matthew.d.roper@intel.com> Reviewed-by: Lucas De Marchi <lucas.demarchi@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220127234334.4016964-6-matthew.d.roper@intel.com
103 lines
2.6 KiB
C
103 lines
2.6 KiB
C
// SPDX-License-Identifier: MIT
|
|
/*
|
|
* Copyright(c) 2020 Intel Corporation.
|
|
*/
|
|
#include <linux/workqueue.h>
|
|
#include "intel_pxp.h"
|
|
#include "intel_pxp_irq.h"
|
|
#include "intel_pxp_session.h"
|
|
#include "gt/intel_gt_irq.h"
|
|
#include "gt/intel_gt_regs.h"
|
|
#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.
|
|
* @pxp: pointer to pxp struct
|
|
* @iir: interrupt vector
|
|
*/
|
|
void intel_pxp_irq_handler(struct intel_pxp *pxp, u16 iir)
|
|
{
|
|
struct intel_gt *gt = pxp_to_gt(pxp);
|
|
|
|
if (GEM_WARN_ON(!intel_pxp_is_enabled(pxp)))
|
|
return;
|
|
|
|
lockdep_assert_held(>->irq_lock);
|
|
|
|
if (unlikely(!iir))
|
|
return;
|
|
|
|
if (iir & (GEN12_DISPLAY_PXP_STATE_TERMINATED_INTERRUPT |
|
|
GEN12_DISPLAY_APP_TERMINATED_PER_FW_REQ_INTERRUPT)) {
|
|
/* immediately mark PXP as inactive on termination */
|
|
intel_pxp_mark_termination_in_progress(pxp);
|
|
pxp->session_events |= PXP_TERMINATION_REQUEST | PXP_INVAL_REQUIRED;
|
|
}
|
|
|
|
if (iir & GEN12_DISPLAY_STATE_RESET_COMPLETE_INTERRUPT)
|
|
pxp->session_events |= PXP_TERMINATION_COMPLETE;
|
|
|
|
if (pxp->session_events)
|
|
queue_work(system_unbound_wq, &pxp->session_work);
|
|
}
|
|
|
|
static inline void __pxp_set_interrupts(struct intel_gt *gt, u32 interrupts)
|
|
{
|
|
struct intel_uncore *uncore = gt->uncore;
|
|
const u32 mask = interrupts << 16;
|
|
|
|
intel_uncore_write(uncore, GEN11_CRYPTO_RSVD_INTR_ENABLE, mask);
|
|
intel_uncore_write(uncore, GEN11_CRYPTO_RSVD_INTR_MASK, ~mask);
|
|
}
|
|
|
|
static inline void pxp_irq_reset(struct intel_gt *gt)
|
|
{
|
|
spin_lock_irq(>->irq_lock);
|
|
gen11_gt_reset_one_iir(gt, 0, GEN11_KCR);
|
|
spin_unlock_irq(>->irq_lock);
|
|
}
|
|
|
|
void intel_pxp_irq_enable(struct intel_pxp *pxp)
|
|
{
|
|
struct intel_gt *gt = pxp_to_gt(pxp);
|
|
|
|
spin_lock_irq(>->irq_lock);
|
|
|
|
if (!pxp->irq_enabled)
|
|
WARN_ON_ONCE(gen11_gt_reset_one_iir(gt, 0, GEN11_KCR));
|
|
|
|
__pxp_set_interrupts(gt, GEN12_PXP_INTERRUPTS);
|
|
pxp->irq_enabled = true;
|
|
|
|
spin_unlock_irq(>->irq_lock);
|
|
}
|
|
|
|
void intel_pxp_irq_disable(struct intel_pxp *pxp)
|
|
{
|
|
struct intel_gt *gt = pxp_to_gt(pxp);
|
|
|
|
/*
|
|
* We always need to submit a global termination when we re-enable the
|
|
* interrupts, so there is no need to make sure that the session state
|
|
* makes sense at the end of this function. Just make sure this is not
|
|
* called in a path were the driver consider the session as valid and
|
|
* doesn't call a termination on restart.
|
|
*/
|
|
GEM_WARN_ON(intel_pxp_is_active(pxp));
|
|
|
|
spin_lock_irq(>->irq_lock);
|
|
|
|
pxp->irq_enabled = false;
|
|
__pxp_set_interrupts(gt, 0);
|
|
|
|
spin_unlock_irq(>->irq_lock);
|
|
intel_synchronize_irq(gt->i915);
|
|
|
|
pxp_irq_reset(gt);
|
|
|
|
flush_work(&pxp->session_work);
|
|
}
|