[Intel-gfx] [PATCH] drm/i915: Assert we hold the CRTC powerwell for generating vblank interrupts

Chris Wilson chris at chris-wilson.co.uk
Mon Oct 10 11:39:05 UTC 2016


To enable the vblank itself, we need to have an RPM wakeref for the mmio
access, and whilst generating the vblank interrupts we continue to
require the rpm wakeref. The assumption is that the RPM wakeref is held
by the display powerwell held by the active pipe. As this chain was not
obvious to me chasing the drm_wait_vblank ioctl, document it with a WARN
during *_vblank_enable().

v2: Check the display power well rather than digging inside the atomic
CRTC state.
v3: Keep the WARN_ON() tidy (avoid macro expansions that get recorded
in their completeness in the user string).

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
Cc: Ville Syrjälä <ville.syrjala at linux.intel.com>
Cc: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
---
 drivers/gpu/drm/i915/i915_irq.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 1e43fe30da11..8e2eb5adde33 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -2715,6 +2715,18 @@ void i915_handle_error(struct drm_i915_private *dev_priv,
 	i915_reset_and_wakeup(dev_priv);
 }
 
+static void assert_pipe_is_awake(struct drm_i915_private *dev_priv,
+				 enum pipe pipe)
+{
+	enum intel_display_power_domain pipe_domain;
+
+	if (!IS_ENABLED(CONFIG_DRM_I915_DEBUG))
+		return;
+
+	pipe_domain = POWER_DOMAIN_PIPE(pipe);
+	WARN_ON(!intel_display_power_is_enabled(dev_priv, pipe_domain));
+}
+
 /* Called from drm generic code, passed 'crtc' which
  * we use as a pipe index
  */
@@ -2723,6 +2735,9 @@ static int i8xx_enable_vblank(struct drm_device *dev, unsigned int pipe)
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	unsigned long irqflags;
 
+	/* vblank IRQ requires the powerwell, held awake by the CRTC */
+	assert_pipe_is_awake(dev_priv, pipe);
+
 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
 	i915_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS);
 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
@@ -2735,6 +2750,9 @@ static int i965_enable_vblank(struct drm_device *dev, unsigned int pipe)
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	unsigned long irqflags;
 
+	/* vblank IRQ requires the powerwell, held awake by the CRTC */
+	assert_pipe_is_awake(dev_priv, pipe);
+
 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
 	i915_enable_pipestat(dev_priv, pipe,
 			     PIPE_START_VBLANK_INTERRUPT_STATUS);
@@ -2750,6 +2768,9 @@ static int ironlake_enable_vblank(struct drm_device *dev, unsigned int pipe)
 	uint32_t bit = INTEL_GEN(dev) >= 7 ?
 		DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe);
 
+	/* vblank IRQ requires the powerwell, held awake by the CRTC */
+	assert_pipe_is_awake(dev_priv, pipe);
+
 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
 	ilk_enable_display_irq(dev_priv, bit);
 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
@@ -2762,6 +2783,9 @@ static int gen8_enable_vblank(struct drm_device *dev, unsigned int pipe)
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	unsigned long irqflags;
 
+	/* vblank IRQ requires the powerwell, held awake by the CRTC */
+	assert_pipe_is_awake(dev_priv, pipe);
+
 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
 	bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK);
 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
-- 
2.9.3



More information about the Intel-gfx mailing list