[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