[PATCH] callbacks-on-vblank

Chris Wilson chris at chris-wilson.co.uk
Thu Aug 17 09:36:36 UTC 2017


---
 drivers/gpu/drm/i915/i915_irq.c      | 46 ++++++++++++++++++++++++++++++------
 drivers/gpu/drm/i915/intel_display.c |  2 ++
 drivers/gpu/drm/i915/intel_drv.h     |  6 +++++
 3 files changed, 47 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index e21ce9c18b6e..7acb31f57352 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1767,6 +1767,38 @@ static void valleyview_pipestat_irq_ack(struct drm_i915_private *dev_priv,
 	spin_unlock(&dev_priv->irq_lock);
 }
 
+static void intel_handle_vblank(struct drm_i915_private *i915, int pipe)
+{
+	struct intel_crtc *crtc = i915->pipe_to_crtc_mapping[pipe];
+
+	drm_handle_vblank(&i915->drm, pipe);
+
+	spin_lock(&crtc->vblank_wq.lock);
+	if (waitqueue_active(&crtc->vblank_wq)) {
+		wake_up_all_locked(&crtc->vblank_wq);
+		if (!waitqueue_active(&crtc->vblank_wq))
+			drm_crtc_vblank_put(&crtc->base);
+	}
+	spin_unlock(&crtc->vblank_wq.lock);
+}
+
+int intel_crtc_add_vblank_wait(struct intel_crtc *crtc,
+			       wait_queue_entry_t *wait)
+{
+	unsigned long flags;
+	int err;
+
+	err = 0;
+	spin_lock_irqsave(&crtc->vblank_wq.lock, flags);
+	if (!waitqueue_active(&crtc->vblank_wq))
+		err = drm_crtc_vblank_get(&crtc->base);
+	if (!err)
+		__add_wait_queue(&crtc->vblank_wq, wait);
+	spin_unlock_irqrestore(&crtc->vblank_wq.lock, flags);
+
+	return err;
+}
+
 static void valleyview_pipestat_irq_handler(struct drm_i915_private *dev_priv,
 					    u32 pipe_stats[I915_MAX_PIPES])
 {
@@ -1774,7 +1806,7 @@ static void valleyview_pipestat_irq_handler(struct drm_i915_private *dev_priv,
 
 	for_each_pipe(dev_priv, pipe) {
 		if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS)
-			drm_handle_vblank(&dev_priv->drm, pipe);
+			intel_handle_vblank(dev_priv, pipe);
 
 		if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
 			i9xx_pipe_crc_irq_handler(dev_priv, pipe);
@@ -2227,7 +2259,7 @@ static void ilk_display_irq_handler(struct drm_i915_private *dev_priv,
 
 	for_each_pipe(dev_priv, pipe) {
 		if (de_iir & DE_PIPE_VBLANK(pipe))
-			drm_handle_vblank(&dev_priv->drm, pipe);
+			intel_handle_vblank(dev_priv, pipe);
 
 		if (de_iir & DE_PIPE_FIFO_UNDERRUN(pipe))
 			intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
@@ -2273,7 +2305,7 @@ static void ivb_display_irq_handler(struct drm_i915_private *dev_priv,
 
 	for_each_pipe(dev_priv, pipe) {
 		if (de_iir & (DE_PIPE_VBLANK_IVB(pipe)))
-			drm_handle_vblank(&dev_priv->drm, pipe);
+			intel_handle_vblank(dev_priv, pipe);
 	}
 
 	/* check event from PCH */
@@ -2469,7 +2501,7 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl)
 		I915_WRITE(GEN8_DE_PIPE_IIR(pipe), iir);
 
 		if (iir & GEN8_PIPE_VBLANK)
-			drm_handle_vblank(&dev_priv->drm, pipe);
+			intel_handle_vblank(dev_priv, pipe);
 
 		if (iir & GEN8_PIPE_CDCLK_CRC_DONE)
 			hsw_pipe_crc_irq_handler(dev_priv, pipe);
@@ -3668,7 +3700,7 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg)
 				plane = !plane;
 
 			if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS)
-				drm_handle_vblank(&dev_priv->drm, pipe);
+				intel_handle_vblank(dev_priv, pipe);
 
 			if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
 				i9xx_pipe_crc_irq_handler(dev_priv, pipe);
@@ -3830,7 +3862,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
 				plane = !plane;
 
 			if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS)
-				drm_handle_vblank(&dev_priv->drm, pipe);
+				intel_handle_vblank(dev_priv, pipe);
 
 			if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
 				blc_event = true;
@@ -4056,7 +4088,7 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
 
 		for_each_pipe(dev_priv, pipe) {
 			if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS)
-				drm_handle_vblank(&dev_priv->drm, pipe);
+				intel_handle_vblank(dev_priv, pipe);
 
 			if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
 				blc_event = true;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 0e93ec201fe3..cd9837694e99 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -13389,6 +13389,8 @@ static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
 	if (!intel_crtc)
 		return -ENOMEM;
 
+	init_waitqueue_head(&intel_crtc->vblank_wq);
+
 	crtc_state = kzalloc(sizeof(*crtc_state), GFP_KERNEL);
 	if (!crtc_state) {
 		ret = -ENOMEM;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index fa47285918f4..832985dbb38d 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -838,6 +838,8 @@ struct intel_crtc {
 
 	/* scalers available on this crtc */
 	int num_scalers;
+
+	struct wait_queue_head vblank_wq;
 };
 
 struct intel_plane {
@@ -1980,4 +1982,8 @@ int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name,
 #define intel_crtc_set_crc_source NULL
 #endif
 extern const struct file_operations i915_display_crc_ctl_fops;
+
+int intel_crtc_add_vblank_wait(struct intel_crtc *crtc,
+			       wait_queue_entry_t *wait);
+
 #endif /* __INTEL_DRV_H__ */
-- 
2.14.1



More information about the Intel-gfx-trybot mailing list