drm/i915/guc: handle interrupts from media GuC
authorDaniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Tue, 8 Nov 2022 02:06:00 +0000 (18:06 -0800)
committerDaniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Mon, 14 Nov 2022 18:11:47 +0000 (10:11 -0800)
The render and media GuCs share the same interrupt enable register, so
we can no longer disable interrupts when we disable communication for
one of the GuCs as this would impact the other GuC. Instead, we keep the
interrupts always enabled in HW and use a variable in the GuC structure
to determine if we want to service the received interrupts or not.

v2: use MTL_ prefix for reg definition (Matt)

Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Matt Roper <matthew.d.roper@intel.com>
Cc: John Harrison <John.C.Harrison@Intel.com>
Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20221108020600.3575467-7-daniele.ceraolospurio@intel.com
drivers/gpu/drm/i915/gt/intel_gt_irq.c
drivers/gpu/drm/i915/gt/intel_gt_regs.h
drivers/gpu/drm/i915/gt/uc/intel_guc.c
drivers/gpu/drm/i915/gt/uc/intel_guc.h
drivers/gpu/drm/i915/gt/uc/intel_uc.c

index 4c8ddd074b7840c1f09a083956b88758f94dbe28..6f6b9e04d916ea23dd36aeaaf9eb8865169b4dae 100644 (file)
@@ -17,6 +17,9 @@
 
 static void guc_irq_handler(struct intel_guc *guc, u16 iir)
 {
+       if (unlikely(!guc->interrupts.enabled))
+               return;
+
        if (iir & GUC_INTR_GUC2HOST)
                intel_guc_to_host_event_handler(guc);
 }
@@ -251,6 +254,7 @@ void gen11_gt_irq_postinstall(struct intel_gt *gt)
 {
        struct intel_uncore *uncore = gt->uncore;
        u32 irqs = GT_RENDER_USER_INTERRUPT;
+       u32 guc_mask = intel_uc_wants_guc(&gt->uc) ? GUC_INTR_GUC2HOST : 0;
        u32 gsc_mask = 0;
        u32 dmask;
        u32 smask;
@@ -305,6 +309,19 @@ void gen11_gt_irq_postinstall(struct intel_gt *gt)
        if (gsc_mask)
                intel_uncore_write(uncore, GEN11_GUNIT_CSME_INTR_MASK, ~gsc_mask);
 
+       if (guc_mask) {
+               /* the enable bit is common for both GTs but the masks are separate */
+               u32 mask = gt->type == GT_MEDIA ?
+                       REG_FIELD_PREP(ENGINE0_MASK, guc_mask) :
+                       REG_FIELD_PREP(ENGINE1_MASK, guc_mask);
+
+               intel_uncore_write(uncore, GEN11_GUC_SG_INTR_ENABLE,
+                                  REG_FIELD_PREP(ENGINE1_MASK, guc_mask));
+
+               /* we might not be the first GT to write this reg */
+               intel_uncore_rmw(uncore, MTL_GUC_MGUC_INTR_MASK, mask, 0);
+       }
+
        /*
         * RPS interrupts will get enabled/disabled on demand when RPS itself
         * is enabled/disabled.
@@ -313,10 +330,6 @@ void gen11_gt_irq_postinstall(struct intel_gt *gt)
        gt->pm_imr = ~gt->pm_ier;
        intel_uncore_write(uncore, GEN11_GPM_WGBOXPERF_INTR_ENABLE, 0);
        intel_uncore_write(uncore, GEN11_GPM_WGBOXPERF_INTR_MASK,  ~0);
-
-       /* Same thing for GuC interrupts */
-       intel_uncore_write(uncore, GEN11_GUC_SG_INTR_ENABLE, 0);
-       intel_uncore_write(uncore, GEN11_GUC_SG_INTR_MASK,  ~0);
 }
 
 void gen5_gt_irq_handler(struct intel_gt *gt, u32 gt_iir)
index 8aa06b0327e515ac50debb758a77f1ed0f061941..a5d596b615a6e34ad96dca828a9396563e75ea53 100644 (file)
 #define   GEN11_CSME                           (31)
 #define   GEN11_GUNIT                          (28)
 #define   GEN11_GUC                            (25)
+#define   MTL_MGUC                             (24)
 #define   GEN11_WDPERF                         (20)
 #define   GEN11_KCR                            (19)
 #define   GEN11_GTPM                           (16)
 #define GEN11_VECS0_VECS1_INTR_MASK            _MMIO(0x1900d0)
 #define GEN12_VECS2_VECS3_INTR_MASK            _MMIO(0x1900d4)
 #define GEN11_GUC_SG_INTR_MASK                 _MMIO(0x1900e8)
+#define MTL_GUC_MGUC_INTR_MASK                 _MMIO(0x1900e8) /* MTL+ */
 #define GEN11_GPM_WGBOXPERF_INTR_MASK          _MMIO(0x1900ec)
 #define GEN11_CRYPTO_RSVD_INTR_MASK            _MMIO(0x1900f0)
 #define GEN11_GUNIT_CSME_INTR_MASK             _MMIO(0x1900f4)
index 13d49048c56888200f7496bd15cd6e952de1de3c..52aede324788e9db073a2bc0ba364120913ca40b 100644 (file)
@@ -98,6 +98,8 @@ static void gen9_enable_guc_interrupts(struct intel_guc *guc)
                     gt->pm_guc_events);
        gen6_gt_pm_enable_irq(gt, gt->pm_guc_events);
        spin_unlock_irq(gt->irq_lock);
+
+       guc->interrupts.enabled = true;
 }
 
 static void gen9_disable_guc_interrupts(struct intel_guc *guc)
@@ -105,6 +107,7 @@ static void gen9_disable_guc_interrupts(struct intel_guc *guc)
        struct intel_gt *gt = guc_to_gt(guc);
 
        assert_rpm_wakelock_held(&gt->i915->runtime_pm);
+       guc->interrupts.enabled = false;
 
        spin_lock_irq(gt->irq_lock);
 
@@ -116,39 +119,39 @@ static void gen9_disable_guc_interrupts(struct intel_guc *guc)
        gen9_reset_guc_interrupts(guc);
 }
 
+static bool __gen11_reset_guc_interrupts(struct intel_gt *gt)
+{
+       u32 irq = gt->type == GT_MEDIA ? MTL_MGUC : GEN11_GUC;
+
+       lockdep_assert_held(gt->irq_lock);
+       return gen11_gt_reset_one_iir(gt, 0, irq);
+}
+
 static void gen11_reset_guc_interrupts(struct intel_guc *guc)
 {
        struct intel_gt *gt = guc_to_gt(guc);
 
        spin_lock_irq(gt->irq_lock);
-       gen11_gt_reset_one_iir(gt, 0, GEN11_GUC);
+       __gen11_reset_guc_interrupts(gt);
        spin_unlock_irq(gt->irq_lock);
 }
 
 static void gen11_enable_guc_interrupts(struct intel_guc *guc)
 {
        struct intel_gt *gt = guc_to_gt(guc);
-       u32 events = REG_FIELD_PREP(ENGINE1_MASK, GUC_INTR_GUC2HOST);
 
        spin_lock_irq(gt->irq_lock);
-       WARN_ON_ONCE(gen11_gt_reset_one_iir(gt, 0, GEN11_GUC));
-       intel_uncore_write(gt->uncore,
-                          GEN11_GUC_SG_INTR_ENABLE, events);
-       intel_uncore_write(gt->uncore,
-                          GEN11_GUC_SG_INTR_MASK, ~events);
+       __gen11_reset_guc_interrupts(gt);
        spin_unlock_irq(gt->irq_lock);
+
+       guc->interrupts.enabled = true;
 }
 
 static void gen11_disable_guc_interrupts(struct intel_guc *guc)
 {
        struct intel_gt *gt = guc_to_gt(guc);
 
-       spin_lock_irq(gt->irq_lock);
-
-       intel_uncore_write(gt->uncore, GEN11_GUC_SG_INTR_MASK, ~0);
-       intel_uncore_write(gt->uncore, GEN11_GUC_SG_INTR_ENABLE, 0);
-
-       spin_unlock_irq(gt->irq_lock);
+       guc->interrupts.enabled = false;
        intel_synchronize_irq(gt->i915);
 
        gen11_reset_guc_interrupts(guc);
index 357873ef692bdb468d0f866ae38afe39db2f8818..1bb3f982928667d680e12f7ba3a630ae34c5ba87 100644 (file)
@@ -78,6 +78,7 @@ struct intel_guc {
 
        /** @interrupts: pointers to GuC interrupt-managing functions. */
        struct {
+               bool enabled;
                void (*reset)(struct intel_guc *guc);
                void (*enable)(struct intel_guc *guc);
                void (*disable)(struct intel_guc *guc);
@@ -330,9 +331,11 @@ retry:
        return err;
 }
 
+/* Only call this from the interrupt handler code */
 static inline void intel_guc_to_host_event_handler(struct intel_guc *guc)
 {
-       intel_guc_ct_event_handler(&guc->ct);
+       if (guc->interrupts.enabled)
+               intel_guc_ct_event_handler(&guc->ct);
 }
 
 /* GuC addresses above GUC_GGTT_TOP also don't map through the GTT */
index 4cd8a787f9e53d90704b7205f618781f356276a6..1d28286e6f066747f5e73c7629082ab9e49de063 100644 (file)
@@ -636,8 +636,10 @@ void intel_uc_runtime_suspend(struct intel_uc *uc)
 {
        struct intel_guc *guc = &uc->guc;
 
-       if (!intel_guc_is_ready(guc))
+       if (!intel_guc_is_ready(guc)) {
+               guc->interrupts.enabled = false;
                return;
+       }
 
        /*
         * Wait for any outstanding CTB before tearing down communication /w the
@@ -657,8 +659,10 @@ void intel_uc_suspend(struct intel_uc *uc)
        intel_wakeref_t wakeref;
        int err;
 
-       if (!intel_guc_is_ready(guc))
+       if (!intel_guc_is_ready(guc)) {
+               guc->interrupts.enabled = false;
                return;
+       }
 
        with_intel_runtime_pm(&uc_to_gt(uc)->i915->runtime_pm, wakeref) {
                err = intel_guc_suspend(guc);