xref: /openbsd-src/sys/dev/pci/drm/i915/pxp/intel_pxp_irq.c (revision f005ef32267c16bdb134f0e9fa4477dbe07c263a)
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