Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 54c52a84 authored by Oscar Mateo's avatar Oscar Mateo Committed by Chris Wilson
Browse files

drm/i915/guc: Correctly handle GuC interrupts on Gen11



Starting Gen11 GuC shares interrupt registers with SG unit
instead of PM. But for now we don't care about SG interrupts.

v2: (Chris)
v3: rebased (Michal)
v4: more bspec pages, use macros, update commit msg (Michal Wi)

Bspec: 19820, 19840, 19841, 20176

Signed-off-by: default avatarOscar Mateo <oscar.mateo@intel.com>
Signed-off-by: default avatarMichal Wajdeczko <michal.wajdeczko@intel.com>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Reviewed-by: default avatarMichał Winiarski <michal.winiarski@intel.com>
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Link: https://patchwork.freedesktop.org/patch/msgid/20190527183613.17076-13-michal.wajdeczko@intel.com
parent 1e83e7a6
Loading
Loading
Loading
Loading
+52 −1
Original line number Diff line number Diff line
@@ -624,6 +624,42 @@ void gen9_disable_guc_interrupts(struct drm_i915_private *dev_priv)
	gen9_reset_guc_interrupts(dev_priv);
}

void gen11_reset_guc_interrupts(struct drm_i915_private *i915)
{
	spin_lock_irq(&i915->irq_lock);
	gen11_reset_one_iir(i915, 0, GEN11_GUC);
	spin_unlock_irq(&i915->irq_lock);
}

void gen11_enable_guc_interrupts(struct drm_i915_private *dev_priv)
{
	spin_lock_irq(&dev_priv->irq_lock);
	if (!dev_priv->guc.interrupts.enabled) {
		u32 events = REG_FIELD_PREP(ENGINE1_MASK,
					    GEN11_GUC_INTR_GUC2HOST);

		WARN_ON_ONCE(gen11_reset_one_iir(dev_priv, 0, GEN11_GUC));
		I915_WRITE(GEN11_GUC_SG_INTR_ENABLE, events);
		I915_WRITE(GEN11_GUC_SG_INTR_MASK, ~events);
		dev_priv->guc.interrupts.enabled = true;
	}
	spin_unlock_irq(&dev_priv->irq_lock);
}

void gen11_disable_guc_interrupts(struct drm_i915_private *dev_priv)
{
	spin_lock_irq(&dev_priv->irq_lock);
	dev_priv->guc.interrupts.enabled = false;

	I915_WRITE(GEN11_GUC_SG_INTR_MASK, ~0);
	I915_WRITE(GEN11_GUC_SG_INTR_ENABLE, 0);

	spin_unlock_irq(&dev_priv->irq_lock);
	synchronize_irq(dev_priv->drm.irq);

	gen11_reset_guc_interrupts(dev_priv);
}

/**
 * bdw_update_port_irq - update DE port interrupt
 * @dev_priv: driver private
@@ -1893,6 +1929,12 @@ static void gen9_guc_irq_handler(struct drm_i915_private *dev_priv, u32 gt_iir)
		intel_guc_to_host_event_handler(&dev_priv->guc);
}

static void gen11_guc_irq_handler(struct drm_i915_private *i915, u16 iir)
{
	if (iir & GEN11_GUC_INTR_GUC2HOST)
		intel_guc_to_host_event_handler(&i915->guc);
}

static void i9xx_pipestat_irq_reset(struct drm_i915_private *dev_priv)
{
	enum pipe pipe;
@@ -3015,6 +3057,9 @@ static void
gen11_other_irq_handler(struct drm_i915_private * const i915,
			const u8 instance, const u16 iir)
{
	if (instance == OTHER_GUC_INSTANCE)
		return gen11_guc_irq_handler(i915, iir);

	if (instance == OTHER_GTPM_INSTANCE)
		return gen11_rps_irq_handler(i915, iir);

@@ -3545,6 +3590,8 @@ static void gen11_gt_irq_reset(struct drm_i915_private *dev_priv)

	I915_WRITE(GEN11_GPM_WGBOXPERF_INTR_ENABLE, 0);
	I915_WRITE(GEN11_GPM_WGBOXPERF_INTR_MASK,  ~0);
	I915_WRITE(GEN11_GUC_SG_INTR_ENABLE, 0);
	I915_WRITE(GEN11_GUC_SG_INTR_MASK,  ~0);
}

static void gen11_irq_reset(struct drm_device *dev)
@@ -4200,6 +4247,10 @@ static void gen11_gt_irq_postinstall(struct drm_i915_private *dev_priv)
	dev_priv->pm_imr = ~dev_priv->pm_ier;
	I915_WRITE(GEN11_GPM_WGBOXPERF_INTR_ENABLE, 0);
	I915_WRITE(GEN11_GPM_WGBOXPERF_INTR_MASK,  ~0);

	/* Same thing for GuC interrupts */
	I915_WRITE(GEN11_GUC_SG_INTR_ENABLE, 0);
	I915_WRITE(GEN11_GUC_SG_INTR_MASK,  ~0);
}

static void icp_irq_postinstall(struct drm_device *dev)
@@ -4707,7 +4758,7 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
	for (i = 0; i < MAX_L3_SLICES; ++i)
		dev_priv->l3_parity.remap_info[i] = NULL;

	if (HAS_GUC_SCHED(dev_priv))
	if (HAS_GUC_SCHED(dev_priv) && INTEL_GEN(dev_priv) < 11)
		dev_priv->pm_guc_events = GEN9_GUC_TO_HOST_INT_EVENT;

	/* Let's track the enabled rps events */
+3 −0
Original line number Diff line number Diff line
@@ -110,5 +110,8 @@ void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv,
void gen9_reset_guc_interrupts(struct drm_i915_private *dev_priv);
void gen9_enable_guc_interrupts(struct drm_i915_private *dev_priv);
void gen9_disable_guc_interrupts(struct drm_i915_private *dev_priv);
void gen11_reset_guc_interrupts(struct drm_i915_private *i915);
void gen11_enable_guc_interrupts(struct drm_i915_private *i915);
void gen11_disable_guc_interrupts(struct drm_i915_private *i915);

#endif /* __I915_IRQ_H__ */
+4 −0
Original line number Diff line number Diff line
@@ -290,6 +290,7 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
#define OTHER_CLASS		4
#define MAX_ENGINE_CLASS	4

#define OTHER_GUC_INSTANCE	0
#define OTHER_GTPM_INSTANCE	1
#define MAX_ENGINE_INSTANCE    3

@@ -7493,6 +7494,9 @@ enum {
#define GEN11_CRYPTO_RSVD_INTR_MASK	_MMIO(0x1900f0)
#define GEN11_GUNIT_CSME_INTR_MASK	_MMIO(0x1900f4)

#define   ENGINE1_MASK			REG_GENMASK(31, 16)
#define   ENGINE0_MASK			REG_GENMASK(15, 0)

#define ILK_DISPLAY_CHICKEN2	_MMIO(0x42004)
/* Required on all Ironlake and Sandybridge according to the B-Spec. */
#define  ILK_ELPIN_409_SELECT	(1 << 25)
+3 −0
Original line number Diff line number Diff line
@@ -88,6 +88,9 @@ void intel_guc_init_early(struct intel_guc *guc)
	guc->handler = intel_guc_to_host_event_handler_nop;
	if (INTEL_GEN(i915) >= 11) {
		guc->notify = gen11_guc_raise_irq;
		guc->interrupts.reset = gen11_reset_guc_interrupts;
		guc->interrupts.enable = gen11_enable_guc_interrupts;
		guc->interrupts.disable = gen11_disable_guc_interrupts;
	} else {
		guc->notify = gen8_guc_raise_irq;
		guc->interrupts.reset = gen9_reset_guc_interrupts;
+18 −0
Original line number Diff line number Diff line
@@ -134,4 +134,22 @@ struct guc_doorbell_info {
#define GUC_WD_VECS_IER			_MMIO(0xC558)
#define GUC_PM_P24C_IER			_MMIO(0xC55C)

/* GuC Interrupt Vector */
#define GEN11_GUC_INTR_GUC2HOST		(1 << 15)
#define GEN11_GUC_INTR_EXEC_ERROR	(1 << 14)
#define GEN11_GUC_INTR_DISPLAY_EVENT	(1 << 13)
#define GEN11_GUC_INTR_SEM_SIG		(1 << 12)
#define GEN11_GUC_INTR_IOMMU2GUC	(1 << 11)
#define GEN11_GUC_INTR_DOORBELL_RANG	(1 << 10)
#define GEN11_GUC_INTR_DMA_DONE		(1 <<  9)
#define GEN11_GUC_INTR_FATAL_ERROR	(1 <<  8)
#define GEN11_GUC_INTR_NOTIF_ERROR	(1 <<  7)
#define GEN11_GUC_INTR_SW_INT_6		(1 <<  6)
#define GEN11_GUC_INTR_SW_INT_5		(1 <<  5)
#define GEN11_GUC_INTR_SW_INT_4		(1 <<  4)
#define GEN11_GUC_INTR_SW_INT_3		(1 <<  3)
#define GEN11_GUC_INTR_SW_INT_2		(1 <<  2)
#define GEN11_GUC_INTR_SW_INT_1		(1 <<  1)
#define GEN11_GUC_INTR_SW_INT_0		(1 <<  0)

#endif