11bb76ff1Sjsg // SPDX-License-Identifier: MIT
21bb76ff1Sjsg /*
31bb76ff1Sjsg * Copyright(c) 2020 Intel Corporation.
41bb76ff1Sjsg */
51bb76ff1Sjsg #include <linux/workqueue.h>
6*f005ef32Sjsg
71bb76ff1Sjsg #include "gt/intel_gt_irq.h"
81bb76ff1Sjsg #include "gt/intel_gt_regs.h"
91bb76ff1Sjsg #include "gt/intel_gt_types.h"
10*f005ef32Sjsg
111bb76ff1Sjsg #include "i915_irq.h"
121bb76ff1Sjsg #include "i915_reg.h"
13*f005ef32Sjsg
14*f005ef32Sjsg #include "intel_pxp.h"
15*f005ef32Sjsg #include "intel_pxp_irq.h"
16*f005ef32Sjsg #include "intel_pxp_session.h"
17*f005ef32Sjsg #include "intel_pxp_types.h"
181bb76ff1Sjsg #include "intel_runtime_pm.h"
191bb76ff1Sjsg
201bb76ff1Sjsg /**
211bb76ff1Sjsg * intel_pxp_irq_handler - Handles PXP interrupts.
221bb76ff1Sjsg * @pxp: pointer to pxp struct
231bb76ff1Sjsg * @iir: interrupt vector
241bb76ff1Sjsg */
intel_pxp_irq_handler(struct intel_pxp * pxp,u16 iir)251bb76ff1Sjsg void intel_pxp_irq_handler(struct intel_pxp *pxp, u16 iir)
261bb76ff1Sjsg {
27*f005ef32Sjsg struct intel_gt *gt;
281bb76ff1Sjsg
291bb76ff1Sjsg if (GEM_WARN_ON(!intel_pxp_is_enabled(pxp)))
301bb76ff1Sjsg return;
311bb76ff1Sjsg
32*f005ef32Sjsg gt = pxp->ctrl_gt;
33*f005ef32Sjsg
341bb76ff1Sjsg lockdep_assert_held(gt->irq_lock);
351bb76ff1Sjsg
361bb76ff1Sjsg if (unlikely(!iir))
371bb76ff1Sjsg return;
381bb76ff1Sjsg
391bb76ff1Sjsg if (iir & (GEN12_DISPLAY_PXP_STATE_TERMINATED_INTERRUPT |
401bb76ff1Sjsg GEN12_DISPLAY_APP_TERMINATED_PER_FW_REQ_INTERRUPT)) {
411bb76ff1Sjsg /* immediately mark PXP as inactive on termination */
421bb76ff1Sjsg intel_pxp_mark_termination_in_progress(pxp);
431bb76ff1Sjsg pxp->session_events |= PXP_TERMINATION_REQUEST | PXP_INVAL_REQUIRED;
441bb76ff1Sjsg }
451bb76ff1Sjsg
461bb76ff1Sjsg if (iir & GEN12_DISPLAY_STATE_RESET_COMPLETE_INTERRUPT)
471bb76ff1Sjsg pxp->session_events |= PXP_TERMINATION_COMPLETE;
481bb76ff1Sjsg
491bb76ff1Sjsg if (pxp->session_events)
501bb76ff1Sjsg queue_work(system_unbound_wq, &pxp->session_work);
511bb76ff1Sjsg }
521bb76ff1Sjsg
__pxp_set_interrupts(struct intel_gt * gt,u32 interrupts)531bb76ff1Sjsg static inline void __pxp_set_interrupts(struct intel_gt *gt, u32 interrupts)
541bb76ff1Sjsg {
551bb76ff1Sjsg struct intel_uncore *uncore = gt->uncore;
561bb76ff1Sjsg const u32 mask = interrupts << 16;
571bb76ff1Sjsg
581bb76ff1Sjsg intel_uncore_write(uncore, GEN11_CRYPTO_RSVD_INTR_ENABLE, mask);
591bb76ff1Sjsg intel_uncore_write(uncore, GEN11_CRYPTO_RSVD_INTR_MASK, ~mask);
601bb76ff1Sjsg }
611bb76ff1Sjsg
pxp_irq_reset(struct intel_gt * gt)621bb76ff1Sjsg static inline void pxp_irq_reset(struct intel_gt *gt)
631bb76ff1Sjsg {
641bb76ff1Sjsg spin_lock_irq(gt->irq_lock);
651bb76ff1Sjsg gen11_gt_reset_one_iir(gt, 0, GEN11_KCR);
661bb76ff1Sjsg spin_unlock_irq(gt->irq_lock);
671bb76ff1Sjsg }
681bb76ff1Sjsg
intel_pxp_irq_enable(struct intel_pxp * pxp)691bb76ff1Sjsg void intel_pxp_irq_enable(struct intel_pxp *pxp)
701bb76ff1Sjsg {
71*f005ef32Sjsg struct intel_gt *gt = pxp->ctrl_gt;
721bb76ff1Sjsg
731bb76ff1Sjsg spin_lock_irq(gt->irq_lock);
741bb76ff1Sjsg
751bb76ff1Sjsg if (!pxp->irq_enabled)
761bb76ff1Sjsg WARN_ON_ONCE(gen11_gt_reset_one_iir(gt, 0, GEN11_KCR));
771bb76ff1Sjsg
781bb76ff1Sjsg __pxp_set_interrupts(gt, GEN12_PXP_INTERRUPTS);
791bb76ff1Sjsg pxp->irq_enabled = true;
801bb76ff1Sjsg
811bb76ff1Sjsg spin_unlock_irq(gt->irq_lock);
821bb76ff1Sjsg }
831bb76ff1Sjsg
intel_pxp_irq_disable(struct intel_pxp * pxp)841bb76ff1Sjsg void intel_pxp_irq_disable(struct intel_pxp *pxp)
851bb76ff1Sjsg {
86*f005ef32Sjsg struct intel_gt *gt = pxp->ctrl_gt;
871bb76ff1Sjsg
881bb76ff1Sjsg /*
891bb76ff1Sjsg * We always need to submit a global termination when we re-enable the
901bb76ff1Sjsg * interrupts, so there is no need to make sure that the session state
911bb76ff1Sjsg * makes sense at the end of this function. Just make sure this is not
921bb76ff1Sjsg * called in a path were the driver consider the session as valid and
931bb76ff1Sjsg * doesn't call a termination on restart.
941bb76ff1Sjsg */
951bb76ff1Sjsg GEM_WARN_ON(intel_pxp_is_active(pxp));
961bb76ff1Sjsg
971bb76ff1Sjsg spin_lock_irq(gt->irq_lock);
981bb76ff1Sjsg
991bb76ff1Sjsg pxp->irq_enabled = false;
1001bb76ff1Sjsg __pxp_set_interrupts(gt, 0);
1011bb76ff1Sjsg
1021bb76ff1Sjsg spin_unlock_irq(gt->irq_lock);
1031bb76ff1Sjsg intel_synchronize_irq(gt->i915);
1041bb76ff1Sjsg
1051bb76ff1Sjsg pxp_irq_reset(gt);
1061bb76ff1Sjsg
1071bb76ff1Sjsg flush_work(&pxp->session_work);
1081bb76ff1Sjsg }
109