drm/i915/guc: handle interrupts from media GuC

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: default avatarDaniele 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: default avatarMatt Roper <matthew.d.roper@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20221108020600.3575467-7-daniele.ceraolospurio@intel.com
parent b910f716
...@@ -17,6 +17,9 @@ ...@@ -17,6 +17,9 @@
static void guc_irq_handler(struct intel_guc *guc, u16 iir) static void guc_irq_handler(struct intel_guc *guc, u16 iir)
{ {
if (unlikely(!guc->interrupts.enabled))
return;
if (iir & GUC_INTR_GUC2HOST) if (iir & GUC_INTR_GUC2HOST)
intel_guc_to_host_event_handler(guc); intel_guc_to_host_event_handler(guc);
} }
...@@ -251,6 +254,7 @@ void gen11_gt_irq_postinstall(struct intel_gt *gt) ...@@ -251,6 +254,7 @@ void gen11_gt_irq_postinstall(struct intel_gt *gt)
{ {
struct intel_uncore *uncore = gt->uncore; struct intel_uncore *uncore = gt->uncore;
u32 irqs = GT_RENDER_USER_INTERRUPT; u32 irqs = GT_RENDER_USER_INTERRUPT;
u32 guc_mask = intel_uc_wants_guc(&gt->uc) ? GUC_INTR_GUC2HOST : 0;
u32 gsc_mask = 0; u32 gsc_mask = 0;
u32 dmask; u32 dmask;
u32 smask; u32 smask;
...@@ -305,6 +309,19 @@ void gen11_gt_irq_postinstall(struct intel_gt *gt) ...@@ -305,6 +309,19 @@ void gen11_gt_irq_postinstall(struct intel_gt *gt)
if (gsc_mask) if (gsc_mask)
intel_uncore_write(uncore, GEN11_GUNIT_CSME_INTR_MASK, ~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 * RPS interrupts will get enabled/disabled on demand when RPS itself
* is enabled/disabled. * is enabled/disabled.
...@@ -313,10 +330,6 @@ void gen11_gt_irq_postinstall(struct intel_gt *gt) ...@@ -313,10 +330,6 @@ void gen11_gt_irq_postinstall(struct intel_gt *gt)
gt->pm_imr = ~gt->pm_ier; gt->pm_imr = ~gt->pm_ier;
intel_uncore_write(uncore, GEN11_GPM_WGBOXPERF_INTR_ENABLE, 0); intel_uncore_write(uncore, GEN11_GPM_WGBOXPERF_INTR_ENABLE, 0);
intel_uncore_write(uncore, GEN11_GPM_WGBOXPERF_INTR_MASK, ~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) void gen5_gt_irq_handler(struct intel_gt *gt, u32 gt_iir)
......
...@@ -1554,6 +1554,7 @@ ...@@ -1554,6 +1554,7 @@
#define GEN11_CSME (31) #define GEN11_CSME (31)
#define GEN11_GUNIT (28) #define GEN11_GUNIT (28)
#define GEN11_GUC (25) #define GEN11_GUC (25)
#define MTL_MGUC (24)
#define GEN11_WDPERF (20) #define GEN11_WDPERF (20)
#define GEN11_KCR (19) #define GEN11_KCR (19)
#define GEN11_GTPM (16) #define GEN11_GTPM (16)
...@@ -1608,6 +1609,7 @@ ...@@ -1608,6 +1609,7 @@
#define GEN11_VECS0_VECS1_INTR_MASK _MMIO(0x1900d0) #define GEN11_VECS0_VECS1_INTR_MASK _MMIO(0x1900d0)
#define GEN12_VECS2_VECS3_INTR_MASK _MMIO(0x1900d4) #define GEN12_VECS2_VECS3_INTR_MASK _MMIO(0x1900d4)
#define GEN11_GUC_SG_INTR_MASK _MMIO(0x1900e8) #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_GPM_WGBOXPERF_INTR_MASK _MMIO(0x1900ec)
#define GEN11_CRYPTO_RSVD_INTR_MASK _MMIO(0x1900f0) #define GEN11_CRYPTO_RSVD_INTR_MASK _MMIO(0x1900f0)
#define GEN11_GUNIT_CSME_INTR_MASK _MMIO(0x1900f4) #define GEN11_GUNIT_CSME_INTR_MASK _MMIO(0x1900f4)
......
...@@ -98,6 +98,8 @@ static void gen9_enable_guc_interrupts(struct intel_guc *guc) ...@@ -98,6 +98,8 @@ static void gen9_enable_guc_interrupts(struct intel_guc *guc)
gt->pm_guc_events); gt->pm_guc_events);
gen6_gt_pm_enable_irq(gt, gt->pm_guc_events); gen6_gt_pm_enable_irq(gt, gt->pm_guc_events);
spin_unlock_irq(gt->irq_lock); spin_unlock_irq(gt->irq_lock);
guc->interrupts.enabled = true;
} }
static void gen9_disable_guc_interrupts(struct intel_guc *guc) static void gen9_disable_guc_interrupts(struct intel_guc *guc)
...@@ -105,6 +107,7 @@ 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); struct intel_gt *gt = guc_to_gt(guc);
assert_rpm_wakelock_held(&gt->i915->runtime_pm); assert_rpm_wakelock_held(&gt->i915->runtime_pm);
guc->interrupts.enabled = false;
spin_lock_irq(gt->irq_lock); spin_lock_irq(gt->irq_lock);
...@@ -116,39 +119,39 @@ static void gen9_disable_guc_interrupts(struct intel_guc *guc) ...@@ -116,39 +119,39 @@ static void gen9_disable_guc_interrupts(struct intel_guc *guc)
gen9_reset_guc_interrupts(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) static void gen11_reset_guc_interrupts(struct intel_guc *guc)
{ {
struct intel_gt *gt = guc_to_gt(guc); struct intel_gt *gt = guc_to_gt(guc);
spin_lock_irq(gt->irq_lock); 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); spin_unlock_irq(gt->irq_lock);
} }
static void gen11_enable_guc_interrupts(struct intel_guc *guc) static void gen11_enable_guc_interrupts(struct intel_guc *guc)
{ {
struct intel_gt *gt = guc_to_gt(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); spin_lock_irq(gt->irq_lock);
WARN_ON_ONCE(gen11_gt_reset_one_iir(gt, 0, GEN11_GUC)); __gen11_reset_guc_interrupts(gt);
intel_uncore_write(gt->uncore,
GEN11_GUC_SG_INTR_ENABLE, events);
intel_uncore_write(gt->uncore,
GEN11_GUC_SG_INTR_MASK, ~events);
spin_unlock_irq(gt->irq_lock); spin_unlock_irq(gt->irq_lock);
guc->interrupts.enabled = true;
} }
static void gen11_disable_guc_interrupts(struct intel_guc *guc) static void gen11_disable_guc_interrupts(struct intel_guc *guc)
{ {
struct intel_gt *gt = guc_to_gt(guc); struct intel_gt *gt = guc_to_gt(guc);
spin_lock_irq(gt->irq_lock); guc->interrupts.enabled = false;
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);
intel_synchronize_irq(gt->i915); intel_synchronize_irq(gt->i915);
gen11_reset_guc_interrupts(guc); gen11_reset_guc_interrupts(guc);
......
...@@ -78,6 +78,7 @@ struct intel_guc { ...@@ -78,6 +78,7 @@ struct intel_guc {
/** @interrupts: pointers to GuC interrupt-managing functions. */ /** @interrupts: pointers to GuC interrupt-managing functions. */
struct { struct {
bool enabled;
void (*reset)(struct intel_guc *guc); void (*reset)(struct intel_guc *guc);
void (*enable)(struct intel_guc *guc); void (*enable)(struct intel_guc *guc);
void (*disable)(struct intel_guc *guc); void (*disable)(struct intel_guc *guc);
...@@ -330,8 +331,10 @@ static inline int intel_guc_send_busy_loop(struct intel_guc *guc, ...@@ -330,8 +331,10 @@ static inline int intel_guc_send_busy_loop(struct intel_guc *guc,
return err; return err;
} }
/* Only call this from the interrupt handler code */
static inline void intel_guc_to_host_event_handler(struct intel_guc *guc) static inline void intel_guc_to_host_event_handler(struct intel_guc *guc)
{ {
if (guc->interrupts.enabled)
intel_guc_ct_event_handler(&guc->ct); intel_guc_ct_event_handler(&guc->ct);
} }
......
...@@ -636,8 +636,10 @@ void intel_uc_runtime_suspend(struct intel_uc *uc) ...@@ -636,8 +636,10 @@ void intel_uc_runtime_suspend(struct intel_uc *uc)
{ {
struct intel_guc *guc = &uc->guc; struct intel_guc *guc = &uc->guc;
if (!intel_guc_is_ready(guc)) if (!intel_guc_is_ready(guc)) {
guc->interrupts.enabled = false;
return; return;
}
/* /*
* Wait for any outstanding CTB before tearing down communication /w the * Wait for any outstanding CTB before tearing down communication /w the
...@@ -657,8 +659,10 @@ void intel_uc_suspend(struct intel_uc *uc) ...@@ -657,8 +659,10 @@ void intel_uc_suspend(struct intel_uc *uc)
intel_wakeref_t wakeref; intel_wakeref_t wakeref;
int err; int err;
if (!intel_guc_is_ready(guc)) if (!intel_guc_is_ready(guc)) {
guc->interrupts.enabled = false;
return; return;
}
with_intel_runtime_pm(&uc_to_gt(uc)->i915->runtime_pm, wakeref) { with_intel_runtime_pm(&uc_to_gt(uc)->i915->runtime_pm, wakeref) {
err = intel_guc_suspend(guc); err = intel_guc_suspend(guc);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment