All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/3] drm/vblank: Introduce drm_crtc_vblank_get_accurate()
@ 2017-06-30 14:18 ville.syrjala
  2017-06-30 14:18 ` [PATCH 2/3] drm/i915: Fix race between pipe update and vblank irq ville.syrjala
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: ville.syrjala @ 2017-06-30 14:18 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Add drm_crtc_vblank_get_accurate() which is the same as
drm_crtc_vblank_get() except that it will forcefully update the
the current vblank counter/timestamp value even if the interrupt
is already enabled.

And we'll switch drm_wait_one_vblank() over to using it to make sure it
will really wait at least one vblank even if it races with the irq
handler.

Cc: Daniel Vetter <daniel@ffwll.ch>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/drm_vblank.c | 37 ++++++++++++++++++++++++++++++++-----
 include/drm/drm_vblank.h     |  1 +
 2 files changed, 33 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c
index 823c853de052..c57383b8753b 100644
--- a/drivers/gpu/drm/drm_vblank.c
+++ b/drivers/gpu/drm/drm_vblank.c
@@ -955,7 +955,8 @@ static int drm_vblank_enable(struct drm_device *dev, unsigned int pipe)
 	return ret;
 }
 
-static int drm_vblank_get(struct drm_device *dev, unsigned int pipe)
+static int drm_vblank_get(struct drm_device *dev, unsigned int pipe,
+			  bool force_update)
 {
 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
 	unsigned long irqflags;
@@ -975,6 +976,10 @@ static int drm_vblank_get(struct drm_device *dev, unsigned int pipe)
 		if (!vblank->enabled) {
 			atomic_dec(&vblank->refcount);
 			ret = -EINVAL;
+		} else if (force_update) {
+			spin_lock(&dev->vblank_time_lock);
+			drm_update_vblank_count(dev, pipe, false);
+			spin_unlock(&dev->vblank_time_lock);
 		}
 	}
 	spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
@@ -994,10 +999,32 @@ static int drm_vblank_get(struct drm_device *dev, unsigned int pipe)
  */
 int drm_crtc_vblank_get(struct drm_crtc *crtc)
 {
-	return drm_vblank_get(crtc->dev, drm_crtc_index(crtc));
+	return drm_vblank_get(crtc->dev, drm_crtc_index(crtc), false);
 }
 EXPORT_SYMBOL(drm_crtc_vblank_get);
 
+/**
+ * drm_crtc_vblank_get_accurate - get a reference count on vblank events and
+ *                                make sure the counter is uptodate
+ * @crtc: which CRTC to own
+ *
+ * Acquire a reference count on vblank events to avoid having them disabled
+ * while in use.
+ *
+ * Also make sure the current vblank counter is value is fully up to date
+ * even if we're already past the start of vblank but the irq hasn't fired
+ * yet, which may be the case with some hardware that raises the interrupt
+ * only some time after the start of vblank.
+ *
+ * Returns:
+ * Zero on success or a negative error code on failure.
+ */
+int drm_crtc_vblank_get_accurate(struct drm_crtc *crtc)
+{
+	return drm_vblank_get(crtc->dev, drm_crtc_index(crtc), true);
+}
+EXPORT_SYMBOL(drm_crtc_vblank_get_accurate);
+
 static void drm_vblank_put(struct drm_device *dev, unsigned int pipe)
 {
 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
@@ -1053,7 +1080,7 @@ void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe)
 	if (WARN_ON(pipe >= dev->num_crtcs))
 		return;
 
-	ret = drm_vblank_get(dev, pipe);
+	ret = drm_vblank_get(dev, pipe, true);
 	if (WARN(ret, "vblank not available on crtc %i, ret=%i\n", pipe, ret))
 		return;
 
@@ -1248,7 +1275,7 @@ static void drm_legacy_vblank_pre_modeset(struct drm_device *dev,
 	 */
 	if (!vblank->inmodeset) {
 		vblank->inmodeset = 0x1;
-		if (drm_vblank_get(dev, pipe) == 0)
+		if (drm_vblank_get(dev, pipe, false) == 0)
 			vblank->inmodeset |= 0x2;
 	}
 }
@@ -1448,7 +1475,7 @@ int drm_wait_vblank_ioctl(struct drm_device *dev, void *data,
 		return 0;
 	}
 
-	ret = drm_vblank_get(dev, pipe);
+	ret = drm_vblank_get(dev, pipe, false);
 	if (ret) {
 		DRM_DEBUG("crtc %d failed to acquire vblank counter, %d\n", pipe, ret);
 		return ret;
diff --git a/include/drm/drm_vblank.h b/include/drm/drm_vblank.h
index 7fba9efe4951..5629e7841318 100644
--- a/include/drm/drm_vblank.h
+++ b/include/drm/drm_vblank.h
@@ -162,6 +162,7 @@ void drm_crtc_arm_vblank_event(struct drm_crtc *crtc,
 bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe);
 bool drm_crtc_handle_vblank(struct drm_crtc *crtc);
 int drm_crtc_vblank_get(struct drm_crtc *crtc);
+int drm_crtc_vblank_get_accurate(struct drm_crtc *crtc);
 void drm_crtc_vblank_put(struct drm_crtc *crtc);
 void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe);
 void drm_crtc_wait_one_vblank(struct drm_crtc *crtc);
-- 
2.13.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2017-07-03 16:47 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-06-30 14:18 [PATCH 1/3] drm/vblank: Introduce drm_crtc_vblank_get_accurate() ville.syrjala
2017-06-30 14:18 ` [PATCH 2/3] drm/i915: Fix race between pipe update and vblank irq ville.syrjala
2017-06-30 14:18 ` [PATCH 3/3] drm/i915: Use drm_crtc_vblank_get_accurate() in intel_atomic_wait_for_vblanks() ville.syrjala
2017-06-30 14:39 ` ✓ Fi.CI.BAT: success for series starting with [1/3] drm/vblank: Introduce drm_crtc_vblank_get_accurate() Patchwork
2017-06-30 15:26 ` [PATCH 1/3] " Daniel Vetter
2017-06-30 18:18   ` Daniel Vetter
2017-07-03 14:26     ` Ville Syrjälä
2017-07-03 16:46       ` Daniel Vetter

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.