[PATCH] adj-vblank

Chris Wilson chris at chris-wilson.co.uk
Sat Jul 28 23:24:37 UTC 2018


What if the vblank interrupt fired before FRAMECOUNT ticked over?
---
 drivers/gpu/drm/drm_vblank.c | 23 +++++++++++++++++------
 include/drm/drm_drv.h        |  1 +
 include/drm/drm_vblank.h     |  1 +
 3 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c
index 28cdcf76b6f9..713e32905543 100644
--- a/drivers/gpu/drm/drm_vblank.c
+++ b/drivers/gpu/drm/drm_vblank.c
@@ -78,7 +78,8 @@
 
 static bool
 drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe,
-			  ktime_t *tvblank, bool in_vblank_irq);
+			  int *adj_vblank, ktime_t *tvblank,
+			  bool in_vblank_irq);
 
 static unsigned int drm_timestamp_precision = 20;  /* Default to 20 usecs. */
 
@@ -145,6 +146,7 @@ static u32 __get_vblank_counter(struct drm_device *dev, unsigned int pipe)
 static void drm_reset_vblank_timestamp(struct drm_device *dev, unsigned int pipe)
 {
 	u32 cur_vblank;
+	int adj_vblank;
 	bool rc;
 	ktime_t t_vblank;
 	int count = DRM_TIMESTAMP_MAXRETRIES;
@@ -157,8 +159,9 @@ static void drm_reset_vblank_timestamp(struct drm_device *dev, unsigned int pipe
 	 */
 	do {
 		cur_vblank = __get_vblank_counter(dev, pipe);
-		rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, false);
+		rc = drm_get_last_vbltimestamp(dev, pipe, &adj_vblank, &t_vblank, false);
 	} while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0);
+	cur_vblank += adj_vblank;
 
 	/*
 	 * Only reinitialize corresponding vblank timestamp if high-precision query
@@ -194,6 +197,7 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
 {
 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
 	u32 cur_vblank, diff;
+	int adj_vblank;
 	bool rc;
 	ktime_t t_vblank;
 	int count = DRM_TIMESTAMP_MAXRETRIES;
@@ -213,8 +217,9 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
 	 */
 	do {
 		cur_vblank = __get_vblank_counter(dev, pipe);
-		rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, in_vblank_irq);
+		rc = drm_get_last_vbltimestamp(dev, pipe, &adj_vblank, &t_vblank, in_vblank_irq);
 	} while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0);
+	cur_vblank += adj_vblank;
 
 	if (dev->max_vblank_count != 0) {
 		/* trust the hw counter when it's around */
@@ -579,6 +584,7 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants);
 bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
 					   unsigned int pipe,
 					   int *max_error,
+					   int *adj_vblank,
 					   ktime_t *vblank_time,
 					   bool in_vblank_irq)
 {
@@ -675,6 +681,7 @@ bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
 	 * vblank_time timestamp for end of vblank.
 	 */
 	*vblank_time = ktime_sub_ns(etime, delta_ns);
+	*adj_vblank = delta_ns < 0;
 
 	if ((drm_debug & DRM_UT_VBL) == 0)
 		return true;
@@ -715,7 +722,8 @@ EXPORT_SYMBOL(drm_calc_vbltimestamp_from_scanoutpos);
  */
 static bool
 drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe,
-			  ktime_t *tvblank, bool in_vblank_irq)
+			  int *adj_vblank, ktime_t *tvblank,
+			  bool in_vblank_irq)
 {
 	bool ret = false;
 
@@ -725,7 +733,7 @@ drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe,
 	/* Query driver if possible and precision timestamping enabled. */
 	if (dev->driver->get_vblank_timestamp && (max_error > 0))
 		ret = dev->driver->get_vblank_timestamp(dev, pipe, &max_error,
-							tvblank, in_vblank_irq);
+							adj_vblank, tvblank, in_vblank_irq);
 
 	/* GPU high precision timestamp query unsupported or failed.
 	 * Return current monotonic/gettimeofday timestamp as best estimate.
@@ -1266,6 +1274,7 @@ void drm_vblank_restore(struct drm_device *dev, unsigned int pipe)
 	int framedur_ns;
 	u64 diff_ns;
 	u32 cur_vblank, diff = 1;
+	int adj_vblank;
 	int count = DRM_TIMESTAMP_MAXRETRIES;
 
 	if (WARN_ON(pipe >= dev->num_crtcs))
@@ -1281,8 +1290,10 @@ void drm_vblank_restore(struct drm_device *dev, unsigned int pipe)
 
 	do {
 		cur_vblank = __get_vblank_counter(dev, pipe);
-		drm_get_last_vbltimestamp(dev, pipe, &t_vblank, false);
+		drm_get_last_vbltimestamp(dev, pipe,
+					  &adj_vblank, &t_vblank, false);
 	} while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0);
+	cur_vblank += adj_vblank;
 
 	diff_ns = ktime_to_ns(ktime_sub(t_vblank, vblank->time));
 	if (framedur_ns)
diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h
index 46a8009784df..92f69fbb78d6 100644
--- a/include/drm/drm_drv.h
+++ b/include/drm/drm_drv.h
@@ -326,6 +326,7 @@ struct drm_driver {
 	 */
 	bool (*get_vblank_timestamp) (struct drm_device *dev, unsigned int pipe,
 				     int *max_error,
+				     int *adj_vblank,
 				     ktime_t *vblank_time,
 				     bool in_vblank_irq);
 
diff --git a/include/drm/drm_vblank.h b/include/drm/drm_vblank.h
index d25a9603ab57..3620a4e5690d 100644
--- a/include/drm/drm_vblank.h
+++ b/include/drm/drm_vblank.h
@@ -201,6 +201,7 @@ void drm_crtc_vblank_restore(struct drm_crtc *crtc);
 
 bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
 					   unsigned int pipe, int *max_error,
+					   int *adj_vblank,
 					   ktime_t *vblank_time,
 					   bool in_vblank_irq);
 void drm_calc_timestamping_constants(struct drm_crtc *crtc,
-- 
2.18.0



More information about the Intel-gfx-trybot mailing list