This function is useful for gen2 intel devices which have no frame counter, but need a way to determine the current vblank count without racing with the vblank interrupt handler.
intel_pipe_update_start checks if no vblank interrupt will occur during vblank evasion, but cannot check whether the vblank handler has run to completion. This function uses the timestamps to determine when the last vblank has happened, and interpolates from there.
Cc: Mario Kleiner mario.kleiner.de@gmail.com Cc: Ville Syrjälä ville.syrjala@linux.intel.com Signed-off-by: Maarten Lankhorst maarten.lankhorst@linux.intel.com --- Unfortunately only compile time tested, I don't have a gen2 to test with.
drivers/gpu/drm/drm_irq.c | 90 +++++++++++++++++++++++++++++++++++------------ include/drm/drmP.h | 2 ++ 2 files changed, 69 insertions(+), 23 deletions(-)
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 881c5a6c180c..44d8f9607ccd 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -155,24 +155,10 @@ static void drm_reset_vblank_timestamp(struct drm_device *dev, unsigned int pipe spin_unlock(&dev->vblank_time_lock); }
-/** - * drm_update_vblank_count - update the master vblank counter - * @dev: DRM device - * @pipe: counter to update - * - * Call back into the driver to update the appropriate vblank counter - * (specified by @pipe). Deal with wraparound, if it occurred, and - * update the last read value so we can deal with wraparound on the next - * call if necessary. - * - * Only necessary when going from off->on, to account for frames we - * didn't get an interrupt for. - * - * Note: caller must hold dev->vbl_lock since this reads & writes - * device vblank fields. - */ -static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, - unsigned long flags) +static u32 __drm_accurate_vblank_count_and_time(struct drm_device *dev, unsigned int pipe, + const struct timeval *t_old, + unsigned long flags, u32 *pdiff, + struct timeval *tv_ret) { struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; u32 cur_vblank, diff; @@ -202,10 +188,8 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, /* trust the hw counter when it's around */ diff = (cur_vblank - vblank->last) & dev->max_vblank_count; } else if (rc && framedur_ns) { - const struct timeval *t_old; u64 diff_ns;
- t_old = &vblanktimestamp(dev, pipe, vblank->count); diff_ns = timeval_to_ns(&t_vblank) - timeval_to_ns(t_old);
/* @@ -286,9 +270,13 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, " current=%u, diff=%u, hw=%u hw_last=%u\n", pipe, vblank->count, diff, cur_vblank, vblank->last);
+ *pdiff = diff; + *tv_ret = t_vblank; + if (diff == 0) { WARN_ON_ONCE(cur_vblank != vblank->last); - return; + + return cur_vblank; }
/* @@ -298,9 +286,65 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, * for now, to mark the vblanktimestamp as invalid. */ if (!rc && (flags & DRM_CALLED_FROM_VBLIRQ) == 0) - t_vblank = (struct timeval) {0, 0}; + *tv_ret = (struct timeval) {0, 0}; + + return cur_vblank; +} + +/** + * drm_accurate_vblank_count_and_time - retrieve the master vblank counter + * @crtc: which counter to retrieve + * @tv_ret: last time counter was updated + * + * This function is similar to @drm_update_vblank_count_and_time but + * this function interpolates to handle a race with vblank irq's, and + * is only useful for crtc's that have no hw vblank counter. + */ + +u32 drm_accurate_vblank_count_and_time(struct drm_crtc *crtc, + struct timeval *tv_ret) +{ + struct drm_device *dev = crtc->dev; + u32 pdiff, old_vblank; + struct timeval tv_old = {}; + + WARN(dev->max_vblank_count, "This function is only useful when a hw counter is unavailable."); + + old_vblank = drm_crtc_vblank_count_and_time(crtc, &tv_old); + + __drm_accurate_vblank_count_and_time(dev, drm_crtc_index(crtc), + &tv_old, 0, &pdiff, tv_ret); + + return old_vblank + pdiff; +} +EXPORT_SYMBOL(drm_accurate_vblank_count_and_time); + +/** + * drm_update_vblank_count - update the master vblank counter + * @dev: DRM device + * @pipe: counter to update + * + * Call back into the driver to update the appropriate vblank counter + * (specified by @pipe). Deal with wraparound, if it occurred, and + * update the last read value so we can deal with wraparound on the next + * call if necessary. + * + * Only necessary when going from off->on, to account for frames we + * didn't get an interrupt for. + * + * Note: caller must hold dev->vbl_lock since this reads & writes + * device vblank fields. + */ +static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, + unsigned long flags) +{ + u32 diff, cur_vblank, old_vblank = dev->vblank[pipe].count; + struct timeval t_vblank; + const struct timeval *tv_old = &vblanktimestamp(dev, pipe, old_vblank);
- store_vblank(dev, pipe, diff, &t_vblank, cur_vblank); + cur_vblank = __drm_accurate_vblank_count_and_time(dev, pipe, tv_old, flags, &diff, &t_vblank); + if (diff) + store_vblank(dev, pipe, diff, &t_vblank, cur_vblank); }
/* diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 31483c2fef51..1df65922c7c6 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -995,6 +995,8 @@ extern void drm_crtc_vblank_off(struct drm_crtc *crtc); extern void drm_crtc_vblank_reset(struct drm_crtc *crtc); extern void drm_crtc_vblank_on(struct drm_crtc *crtc); extern void drm_vblank_cleanup(struct drm_device *dev); +extern u32 drm_accurate_vblank_count_and_time(struct drm_crtc *crtc, + struct timeval *tv_ret); extern u32 drm_vblank_no_hw_counter(struct drm_device *dev, unsigned int pipe);
extern int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
On Tue, Mar 29, 2016 at 03:38:55PM +0200, Maarten Lankhorst wrote:
This function is useful for gen2 intel devices which have no frame counter, but need a way to determine the current vblank count without racing with the vblank interrupt handler.
intel_pipe_update_start checks if no vblank interrupt will occur during vblank evasion, but cannot check whether the vblank handler has run to completion. This function uses the timestamps to determine when the last vblank has happened, and interpolates from there.
Didn't really read it in detail, but on a glance it seems too complicated to me. All we should really need is something like this:
drm_vblank_get(); drm_update_vblank_count(); accurate = drm_vblank_count();
Cc: Mario Kleiner mario.kleiner.de@gmail.com Cc: Ville Syrjälä ville.syrjala@linux.intel.com Signed-off-by: Maarten Lankhorst maarten.lankhorst@linux.intel.com
Unfortunately only compile time tested, I don't have a gen2 to test with.
drivers/gpu/drm/drm_irq.c | 90 +++++++++++++++++++++++++++++++++++------------ include/drm/drmP.h | 2 ++ 2 files changed, 69 insertions(+), 23 deletions(-)
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 881c5a6c180c..44d8f9607ccd 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -155,24 +155,10 @@ static void drm_reset_vblank_timestamp(struct drm_device *dev, unsigned int pipe spin_unlock(&dev->vblank_time_lock); }
-/**
- drm_update_vblank_count - update the master vblank counter
- @dev: DRM device
- @pipe: counter to update
- Call back into the driver to update the appropriate vblank counter
- (specified by @pipe). Deal with wraparound, if it occurred, and
- update the last read value so we can deal with wraparound on the next
- call if necessary.
- Only necessary when going from off->on, to account for frames we
- didn't get an interrupt for.
- Note: caller must hold dev->vbl_lock since this reads & writes
- device vblank fields.
- */
-static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
unsigned long flags)
+static u32 __drm_accurate_vblank_count_and_time(struct drm_device *dev, unsigned int pipe,
const struct timeval *t_old,
unsigned long flags, u32 *pdiff,
struct timeval *tv_ret)
{ struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; u32 cur_vblank, diff; @@ -202,10 +188,8 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, /* trust the hw counter when it's around */ diff = (cur_vblank - vblank->last) & dev->max_vblank_count; } else if (rc && framedur_ns) {
const struct timeval *t_old;
u64 diff_ns;
t_old = &vblanktimestamp(dev, pipe, vblank->count);
diff_ns = timeval_to_ns(&t_vblank) - timeval_to_ns(t_old);
/*
@@ -286,9 +270,13 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, " current=%u, diff=%u, hw=%u hw_last=%u\n", pipe, vblank->count, diff, cur_vblank, vblank->last);
- *pdiff = diff;
- *tv_ret = t_vblank;
- if (diff == 0) { WARN_ON_ONCE(cur_vblank != vblank->last);
return;
return cur_vblank;
}
/*
@@ -298,9 +286,65 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, * for now, to mark the vblanktimestamp as invalid. */ if (!rc && (flags & DRM_CALLED_FROM_VBLIRQ) == 0)
t_vblank = (struct timeval) {0, 0};
*tv_ret = (struct timeval) {0, 0};
- return cur_vblank;
+}
+/**
- drm_accurate_vblank_count_and_time - retrieve the master vblank counter
- @crtc: which counter to retrieve
- @tv_ret: last time counter was updated
- This function is similar to @drm_update_vblank_count_and_time but
- this function interpolates to handle a race with vblank irq's, and
- is only useful for crtc's that have no hw vblank counter.
- */
+u32 drm_accurate_vblank_count_and_time(struct drm_crtc *crtc,
struct timeval *tv_ret)
+{
- struct drm_device *dev = crtc->dev;
- u32 pdiff, old_vblank;
- struct timeval tv_old = {};
- WARN(dev->max_vblank_count, "This function is only useful when a hw counter is unavailable.");
- old_vblank = drm_crtc_vblank_count_and_time(crtc, &tv_old);
- __drm_accurate_vblank_count_and_time(dev, drm_crtc_index(crtc),
&tv_old, 0, &pdiff, tv_ret);
- return old_vblank + pdiff;
+} +EXPORT_SYMBOL(drm_accurate_vblank_count_and_time);
+/**
- drm_update_vblank_count - update the master vblank counter
- @dev: DRM device
- @pipe: counter to update
- Call back into the driver to update the appropriate vblank counter
- (specified by @pipe). Deal with wraparound, if it occurred, and
- update the last read value so we can deal with wraparound on the next
- call if necessary.
- Only necessary when going from off->on, to account for frames we
- didn't get an interrupt for.
- Note: caller must hold dev->vbl_lock since this reads & writes
- device vblank fields.
- */
+static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
unsigned long flags)
+{
- u32 diff, cur_vblank, old_vblank = dev->vblank[pipe].count;
- struct timeval t_vblank;
- const struct timeval *tv_old = &vblanktimestamp(dev, pipe, old_vblank);
- store_vblank(dev, pipe, diff, &t_vblank, cur_vblank);
- cur_vblank = __drm_accurate_vblank_count_and_time(dev, pipe, tv_old, flags, &diff, &t_vblank);
- if (diff)
store_vblank(dev, pipe, diff, &t_vblank, cur_vblank);
}
/* diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 31483c2fef51..1df65922c7c6 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -995,6 +995,8 @@ extern void drm_crtc_vblank_off(struct drm_crtc *crtc); extern void drm_crtc_vblank_reset(struct drm_crtc *crtc); extern void drm_crtc_vblank_on(struct drm_crtc *crtc); extern void drm_vblank_cleanup(struct drm_device *dev); +extern u32 drm_accurate_vblank_count_and_time(struct drm_crtc *crtc,
struct timeval *tv_ret);
extern u32 drm_vblank_no_hw_counter(struct drm_device *dev, unsigned int pipe);
extern int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
2.1.0
Op 30-03-16 om 15:13 schreef Ville Syrjälä:
On Tue, Mar 29, 2016 at 03:38:55PM +0200, Maarten Lankhorst wrote:
This function is useful for gen2 intel devices which have no frame counter, but need a way to determine the current vblank count without racing with the vblank interrupt handler.
intel_pipe_update_start checks if no vblank interrupt will occur during vblank evasion, but cannot check whether the vblank handler has run to completion. This function uses the timestamps to determine when the last vblank has happened, and interpolates from there.
Didn't really read it in detail, but on a glance it seems too complicated to me. All we should really need is something like this:
drm_vblank_get(); drm_update_vblank_count(); accurate = drm_vblank_count();
Updating from non vblank irq context might cause the vblank clock to drift, or at least contend the vblank lock.
This is why I call drm_vblank_count_and_time, and then interpolate as if update_vblank_count was called on the result.
~Maarten
On Wed, Mar 30, 2016 at 03:41:26PM +0200, Maarten Lankhorst wrote:
Op 30-03-16 om 15:13 schreef Ville Syrjälä:
On Tue, Mar 29, 2016 at 03:38:55PM +0200, Maarten Lankhorst wrote:
This function is useful for gen2 intel devices which have no frame counter, but need a way to determine the current vblank count without racing with the vblank interrupt handler.
intel_pipe_update_start checks if no vblank interrupt will occur during vblank evasion, but cannot check whether the vblank handler has run to completion. This function uses the timestamps to determine when the last vblank has happened, and interpolates from there.
Didn't really read it in detail, but on a glance it seems too complicated to me. All we should really need is something like this:
drm_vblank_get(); drm_update_vblank_count(); accurate = drm_vblank_count();
Updating from non vblank irq context might cause the vblank clock to drift, or at least contend the vblank lock.
I don't see a problem. The scanout position is anyway used to fix up the timestamp.
This is why I call drm_vblank_count_and_time, and then interpolate as if update_vblank_count was called on the result.
~Maarten
This function is useful for gen2 intel devices which have no frame counter, but need a way to determine the current vblank count without racing with the vblank interrupt handler.
intel_pipe_update_start checks if no vblank interrupt will occur during vblank evasion, but cannot check whether the vblank handler has run to completion. This function uses the timestamps to determine when the last vblank has happened, and interpolates from there.
Changes since v1: - Take vblank_time_lock and don't use drm_vblank_count_and_time.
Cc: Mario Kleiner mario.kleiner.de@gmail.com Cc: Ville Syrjälä ville.syrjala@linux.intel.com Signed-off-by: Maarten Lankhorst maarten.lankhorst@linux.intel.com --- drivers/gpu/drm/drm_irq.c | 31 +++++++++++++++++++++++++++++++ include/drm/drmP.h | 2 ++ 2 files changed, 33 insertions(+)
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 3c1a6f18e71c..d3cecc1932e1 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -303,6 +303,37 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, store_vblank(dev, pipe, diff, &t_vblank, cur_vblank); }
+/** + * drm_accurate_vblank_count_and_time - retrieve the master vblank counter + * @crtc: which counter to retrieve + * @tv_ret: last time counter was updated + * + * This function is similar to @drm_update_vblank_count_and_time but + * this function interpolates to handle a race with vblank irq's, and + * is only useful for crtc's that have no hw vblank counter. + */ + +u32 drm_accurate_vblank_count_and_time(struct drm_crtc *crtc, + struct timeval *tv_ret) +{ + struct drm_device *dev = crtc->dev; + u32 vblank, pipe = drm_crtc_index(crtc); + unsigned long flags; + + WARN(dev->max_vblank_count, "This function is only useful when a hw counter is unavailable."); + + spin_lock_irqsave(&dev->vblank_time_lock, flags); + drm_update_vblank_count(dev, pipe, 0); + + vblank = dev->vblank[pipe].count; + *tv_ret = vblanktimestamp(dev, pipe, vblank); + + spin_unlock_irqrestore(&dev->vblank_time_lock, flags); + + return vblank; +} +EXPORT_SYMBOL(drm_accurate_vblank_count_and_time); + /* * Disable vblank irq's on crtc, make sure that last vblank count * of hardware and corresponding consistent software vblank counter diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 31483c2fef51..1df65922c7c6 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -995,6 +995,8 @@ extern void drm_crtc_vblank_off(struct drm_crtc *crtc); extern void drm_crtc_vblank_reset(struct drm_crtc *crtc); extern void drm_crtc_vblank_on(struct drm_crtc *crtc); extern void drm_vblank_cleanup(struct drm_device *dev); +extern u32 drm_accurate_vblank_count_and_time(struct drm_crtc *crtc, + struct timeval *tv_ret); extern u32 drm_vblank_no_hw_counter(struct drm_device *dev, unsigned int pipe);
extern int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
On Mon, Apr 11, 2016 at 11:42:57AM +0200, Maarten Lankhorst wrote:
This function is useful for gen2 intel devices which have no frame counter, but need a way to determine the current vblank count without racing with the vblank interrupt handler.
intel_pipe_update_start checks if no vblank interrupt will occur during vblank evasion, but cannot check whether the vblank handler has run to completion. This function uses the timestamps to determine when the last vblank has happened, and interpolates from there.
Changes since v1:
- Take vblank_time_lock and don't use drm_vblank_count_and_time.
Cc: Mario Kleiner mario.kleiner.de@gmail.com Cc: Ville Syrjälä ville.syrjala@linux.intel.com Signed-off-by: Maarten Lankhorst maarten.lankhorst@linux.intel.com
drivers/gpu/drm/drm_irq.c | 31 +++++++++++++++++++++++++++++++ include/drm/drmP.h | 2 ++ 2 files changed, 33 insertions(+)
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 3c1a6f18e71c..d3cecc1932e1 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -303,6 +303,37 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, store_vblank(dev, pipe, diff, &t_vblank, cur_vblank); }
+/**
- drm_accurate_vblank_count_and_time - retrieve the master vblank counter
- @crtc: which counter to retrieve
- @tv_ret: last time counter was updated
- This function is similar to @drm_update_vblank_count_and_time but
- this function interpolates to handle a race with vblank irq's, and
- is only useful for crtc's that have no hw vblank counter.
- */
+u32 drm_accurate_vblank_count_and_time(struct drm_crtc *crtc,
struct timeval *tv_ret)
+{
- struct drm_device *dev = crtc->dev;
- u32 vblank, pipe = drm_crtc_index(crtc);
- unsigned long flags;
- WARN(dev->max_vblank_count, "This function is only useful when a hw counter is unavailable.");
It's useful on everything if you actually want to trust the software counter to not be stale.
- spin_lock_irqsave(&dev->vblank_time_lock, flags);
- drm_update_vblank_count(dev, pipe, 0);
- vblank = dev->vblank[pipe].count;
- *tv_ret = vblanktimestamp(dev, pipe, vblank);
Do we have a user in mind that would care about the timestamp?
- spin_unlock_irqrestore(&dev->vblank_time_lock, flags);
- return vblank;
+} +EXPORT_SYMBOL(drm_accurate_vblank_count_and_time);
/*
- Disable vblank irq's on crtc, make sure that last vblank count
- of hardware and corresponding consistent software vblank counter
diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 31483c2fef51..1df65922c7c6 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -995,6 +995,8 @@ extern void drm_crtc_vblank_off(struct drm_crtc *crtc); extern void drm_crtc_vblank_reset(struct drm_crtc *crtc); extern void drm_crtc_vblank_on(struct drm_crtc *crtc); extern void drm_vblank_cleanup(struct drm_device *dev); +extern u32 drm_accurate_vblank_count_and_time(struct drm_crtc *crtc,
struct timeval *tv_ret);
extern u32 drm_vblank_no_hw_counter(struct drm_device *dev, unsigned int pipe);
extern int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
2.1.0
Op 11-04-16 om 16:43 schreef Ville Syrjälä:
On Mon, Apr 11, 2016 at 11:42:57AM +0200, Maarten Lankhorst wrote:
This function is useful for gen2 intel devices which have no frame counter, but need a way to determine the current vblank count without racing with the vblank interrupt handler.
intel_pipe_update_start checks if no vblank interrupt will occur during vblank evasion, but cannot check whether the vblank handler has run to completion. This function uses the timestamps to determine when the last vblank has happened, and interpolates from there.
Changes since v1:
- Take vblank_time_lock and don't use drm_vblank_count_and_time.
Cc: Mario Kleiner mario.kleiner.de@gmail.com Cc: Ville Syrjälä ville.syrjala@linux.intel.com Signed-off-by: Maarten Lankhorst maarten.lankhorst@linux.intel.com
drivers/gpu/drm/drm_irq.c | 31 +++++++++++++++++++++++++++++++ include/drm/drmP.h | 2 ++ 2 files changed, 33 insertions(+)
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 3c1a6f18e71c..d3cecc1932e1 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -303,6 +303,37 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, store_vblank(dev, pipe, diff, &t_vblank, cur_vblank); }
+/**
- drm_accurate_vblank_count_and_time - retrieve the master vblank counter
- @crtc: which counter to retrieve
- @tv_ret: last time counter was updated
- This function is similar to @drm_update_vblank_count_and_time but
- this function interpolates to handle a race with vblank irq's, and
- is only useful for crtc's that have no hw vblank counter.
- */
+u32 drm_accurate_vblank_count_and_time(struct drm_crtc *crtc,
struct timeval *tv_ret)
+{
- struct drm_device *dev = crtc->dev;
- u32 vblank, pipe = drm_crtc_index(crtc);
- unsigned long flags;
- WARN(dev->max_vblank_count, "This function is only useful when a hw counter is unavailable.");
It's useful on everything if you actually want to trust the software counter to not be stale.
- spin_lock_irqsave(&dev->vblank_time_lock, flags);
- drm_update_vblank_count(dev, pipe, 0);
- vblank = dev->vblank[pipe].count;
- *tv_ret = vblanktimestamp(dev, pipe, vblank);
Do we have a user in mind that would care about the timestamp?
No, I guess allowing a NULL pointer for tv_ret might help.
~Maarten
On Mon, Apr 11, 2016 at 05:06:24PM +0200, Maarten Lankhorst wrote:
Op 11-04-16 om 16:43 schreef Ville Syrjälä:
On Mon, Apr 11, 2016 at 11:42:57AM +0200, Maarten Lankhorst wrote:
This function is useful for gen2 intel devices which have no frame counter, but need a way to determine the current vblank count without racing with the vblank interrupt handler.
intel_pipe_update_start checks if no vblank interrupt will occur during vblank evasion, but cannot check whether the vblank handler has run to completion. This function uses the timestamps to determine when the last vblank has happened, and interpolates from there.
Changes since v1:
- Take vblank_time_lock and don't use drm_vblank_count_and_time.
Cc: Mario Kleiner mario.kleiner.de@gmail.com Cc: Ville Syrjälä ville.syrjala@linux.intel.com Signed-off-by: Maarten Lankhorst maarten.lankhorst@linux.intel.com
drivers/gpu/drm/drm_irq.c | 31 +++++++++++++++++++++++++++++++ include/drm/drmP.h | 2 ++ 2 files changed, 33 insertions(+)
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 3c1a6f18e71c..d3cecc1932e1 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -303,6 +303,37 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, store_vblank(dev, pipe, diff, &t_vblank, cur_vblank); }
+/**
- drm_accurate_vblank_count_and_time - retrieve the master vblank counter
- @crtc: which counter to retrieve
- @tv_ret: last time counter was updated
- This function is similar to @drm_update_vblank_count_and_time but
- this function interpolates to handle a race with vblank irq's, and
- is only useful for crtc's that have no hw vblank counter.
- */
+u32 drm_accurate_vblank_count_and_time(struct drm_crtc *crtc,
struct timeval *tv_ret)
+{
- struct drm_device *dev = crtc->dev;
- u32 vblank, pipe = drm_crtc_index(crtc);
- unsigned long flags;
- WARN(dev->max_vblank_count, "This function is only useful when a hw counter is unavailable.");
It's useful on everything if you actually want to trust the software counter to not be stale.
- spin_lock_irqsave(&dev->vblank_time_lock, flags);
- drm_update_vblank_count(dev, pipe, 0);
- vblank = dev->vblank[pipe].count;
- *tv_ret = vblanktimestamp(dev, pipe, vblank);
Do we have a user in mind that would care about the timestamp?
No, I guess allowing a NULL pointer for tv_ret might help.
Or just killing the entire parameter.
This function is useful for gen2 intel devices which have no frame counter, but need a way to determine the current vblank count without racing with the vblank interrupt handler.
intel_pipe_update_start checks if no vblank interrupt will occur during vblank evasion, but cannot check whether the vblank handler has run to completion. This function uses the timestamps to determine when the last vblank has happened, and interpolates from there.
Changes since v1: - Take vblank_time_lock and don't use drm_vblank_count_and_time. Changes since v2: - Don't return time of last vblank.
Cc: Mario Kleiner mario.kleiner.de@gmail.com Cc: Ville Syrjälä ville.syrjala@linux.intel.com Signed-off-by: Maarten Lankhorst maarten.lankhorst@linux.intel.com --- diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 3c1a6f18e71c..32bfa4bb8f41 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -303,6 +303,32 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, store_vblank(dev, pipe, diff, &t_vblank, cur_vblank); }
+/** + * drm_accurate_vblank_count - retrieve the master vblank counter + * @crtc: which counter to retrieve + * @tv_ret: last time counter was updated + * + * This function is similar to @drm_crtc_vblank_count but this + * function interpolates to handle a race with vblank irq's. + */ + +u32 drm_accurate_vblank_count(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + u32 vblank, pipe = drm_crtc_index(crtc); + unsigned long flags; + + spin_lock_irqsave(&dev->vblank_time_lock, flags); + + drm_update_vblank_count(dev, pipe, 0); + vblank = dev->vblank[pipe].count; + + spin_unlock_irqrestore(&dev->vblank_time_lock, flags); + + return vblank; +} +EXPORT_SYMBOL(drm_accurate_vblank_count); + /* * Disable vblank irq's on crtc, make sure that last vblank count * of hardware and corresponding consistent software vblank counter diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 31483c2fef51..747c80da70e5 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -995,6 +995,7 @@ extern void drm_crtc_vblank_off(struct drm_crtc *crtc); extern void drm_crtc_vblank_reset(struct drm_crtc *crtc); extern void drm_crtc_vblank_on(struct drm_crtc *crtc); extern void drm_vblank_cleanup(struct drm_device *dev); +extern u32 drm_accurate_vblank_count(struct drm_crtc *crtc); extern u32 drm_vblank_no_hw_counter(struct drm_device *dev, unsigned int pipe);
extern int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
On Tue, Apr 12, 2016 at 04:32:19PM +0200, Maarten Lankhorst wrote:
This function is useful for gen2 intel devices which have no frame counter, but need a way to determine the current vblank count without racing with the vblank interrupt handler.
intel_pipe_update_start checks if no vblank interrupt will occur during vblank evasion, but cannot check whether the vblank handler has run to completion. This function uses the timestamps to determine when the last vblank has happened, and interpolates from there.
Changes since v1:
- Take vblank_time_lock and don't use drm_vblank_count_and_time.
Changes since v2:
- Don't return time of last vblank.
Cc: Mario Kleiner mario.kleiner.de@gmail.com Cc: Ville Syrjälä ville.syrjala@linux.intel.com Signed-off-by: Maarten Lankhorst maarten.lankhorst@linux.intel.com
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 3c1a6f18e71c..32bfa4bb8f41 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -303,6 +303,32 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, store_vblank(dev, pipe, diff, &t_vblank, cur_vblank); }
+/**
- drm_accurate_vblank_count - retrieve the master vblank counter
- @crtc: which counter to retrieve
- @tv_ret: last time counter was updated
- This function is similar to @drm_crtc_vblank_count but this
- function interpolates to handle a race with vblank irq's.
- */
+u32 drm_accurate_vblank_count(struct drm_crtc *crtc) +{
- struct drm_device *dev = crtc->dev;
- u32 vblank, pipe = drm_crtc_index(crtc);
pipe should be 'unsigned int' for consistency.
- unsigned long flags;
- spin_lock_irqsave(&dev->vblank_time_lock, flags);
- drm_update_vblank_count(dev, pipe, 0);
One thing that came to mind is some callers might end up doing the update twice if the irq wasn't yet enabled when drm_vblank_get() was called. Eg. drm_wait_one_vblank() might do that. So it might be a bit more efficient to add a drm_vblank_get_and_update() instead, or something like that. But I don't really care too much.
Reviewed-by: Ville Syrjälä ville.syrjala@linux.intel.com
- vblank = dev->vblank[pipe].count;
- spin_unlock_irqrestore(&dev->vblank_time_lock, flags);
- return vblank;
+} +EXPORT_SYMBOL(drm_accurate_vblank_count);
/*
- Disable vblank irq's on crtc, make sure that last vblank count
- of hardware and corresponding consistent software vblank counter
diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 31483c2fef51..747c80da70e5 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -995,6 +995,7 @@ extern void drm_crtc_vblank_off(struct drm_crtc *crtc); extern void drm_crtc_vblank_reset(struct drm_crtc *crtc); extern void drm_crtc_vblank_on(struct drm_crtc *crtc); extern void drm_vblank_cleanup(struct drm_device *dev); +extern u32 drm_accurate_vblank_count(struct drm_crtc *crtc); extern u32 drm_vblank_no_hw_counter(struct drm_device *dev, unsigned int pipe);
extern int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
Hi Maarten,
[auto build test WARNING on drm/drm-next] [also build test WARNING on v4.6-rc3 next-20160412] [if your patch is applied to the wrong git tree, please drop us a note to help improving the system]
url: https://github.com/0day-ci/linux/commits/Maarten-Lankhorst/drm-core-Add-drm_... base: git://people.freedesktop.org/~airlied/linux.git drm-next reproduce: make htmldocs
All warnings (new ones prefixed by >>):
drivers/gpu/drm/i915/i915_irq.c:2663: warning: No description found for parameter 'fmt' include/drm/drm_crtc.h:364: warning: No description found for parameter 'mode_blob' include/drm/drm_crtc.h:779: warning: No description found for parameter 'name' include/drm/drm_crtc.h:1238: warning: No description found for parameter 'connector_id' include/drm/drm_crtc.h:1238: warning: No description found for parameter 'tile_blob_ptr' include/drm/drm_crtc.h:1277: warning: No description found for parameter 'rotation' include/drm/drm_crtc.h:1539: warning: No description found for parameter 'name' include/drm/drm_crtc.h:1539: warning: No description found for parameter 'mutex' include/drm/drm_crtc.h:1539: warning: No description found for parameter 'helper_private' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'tile_idr' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'connector_ida' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'delayed_event' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'edid_property' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'dpms_property' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'path_property' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'tile_property' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'plane_type_property' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'rotation_property' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'prop_src_x' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'prop_src_y' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'prop_src_w' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'prop_src_h' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'prop_crtc_x' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'prop_crtc_y' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'prop_crtc_w' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'prop_crtc_h' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'prop_fb_id' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'prop_crtc_id' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'prop_active' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'prop_mode_id' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'dvi_i_subconnector_property' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'dvi_i_select_subconnector_property' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'tv_subconnector_property' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'tv_select_subconnector_property' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'tv_mode_property' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'tv_left_margin_property' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'tv_right_margin_property' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'tv_top_margin_property' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'tv_bottom_margin_property' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'tv_brightness_property' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'tv_contrast_property' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'tv_flicker_reduction_property' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'tv_overscan_property' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'tv_saturation_property' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'tv_hue_property' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'scaling_mode_property' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'aspect_ratio_property' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'dirty_info_property' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'suggested_x_property' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'suggested_y_property' include/drm/drm_crtc.h:2175: warning: No description found for parameter 'allow_fb_modifiers' drivers/gpu/drm/drm_atomic_helper.c:2924: warning: No description found for parameter 'start' drivers/gpu/drm/drm_atomic_helper.c:2924: warning: No description found for parameter 'start' drivers/gpu/drm/drm_atomic_helper.c:2924: warning: No description found for parameter 'start' drivers/gpu/drm/drm_atomic_helper.c:2924: warning: No description found for parameter 'start' include/drm/drm_dp_helper.h:749: warning: No description found for parameter 'i2c_nack_count' include/drm/drm_dp_helper.h:749: warning: No description found for parameter 'i2c_defer_count' drivers/gpu/drm/drm_dp_mst_topology.c:2356: warning: No description found for parameter 'connector' include/drm/drm_dp_mst_helper.h:92: warning: No description found for parameter 'cached_edid' include/drm/drm_dp_mst_helper.h:92: warning: No description found for parameter 'has_audio' include/drm/drm_dp_mst_helper.h:466: warning: No description found for parameter 'max_dpcd_transaction_bytes' include/drm/drm_dp_mst_helper.h:466: warning: No description found for parameter 'sink_count' include/drm/drm_dp_mst_helper.h:466: warning: No description found for parameter 'total_slots' include/drm/drm_dp_mst_helper.h:466: warning: No description found for parameter 'avail_slots' include/drm/drm_dp_mst_helper.h:466: warning: No description found for parameter 'total_pbn' include/drm/drm_dp_mst_helper.h:466: warning: No description found for parameter 'qlock' include/drm/drm_dp_mst_helper.h:466: warning: No description found for parameter 'tx_msg_downq' include/drm/drm_dp_mst_helper.h:466: warning: No description found for parameter 'tx_down_in_progress' include/drm/drm_dp_mst_helper.h:466: warning: No description found for parameter 'payload_lock' include/drm/drm_dp_mst_helper.h:466: warning: No description found for parameter 'proposed_vcpis' include/drm/drm_dp_mst_helper.h:466: warning: No description found for parameter 'payloads' include/drm/drm_dp_mst_helper.h:466: warning: No description found for parameter 'payload_mask' include/drm/drm_dp_mst_helper.h:466: warning: No description found for parameter 'vcpi_mask' include/drm/drm_dp_mst_helper.h:466: warning: No description found for parameter 'tx_waitq' include/drm/drm_dp_mst_helper.h:466: warning: No description found for parameter 'work' include/drm/drm_dp_mst_helper.h:466: warning: No description found for parameter 'tx_work' include/drm/drm_dp_mst_helper.h:466: warning: No description found for parameter 'destroy_connector_list' include/drm/drm_dp_mst_helper.h:466: warning: No description found for parameter 'destroy_connector_lock' include/drm/drm_dp_mst_helper.h:466: warning: No description found for parameter 'destroy_connector_work' drivers/gpu/drm/drm_dp_mst_topology.c:2356: warning: No description found for parameter 'connector' drivers/gpu/drm/drm_irq.c:176: warning: No description found for parameter 'flags'
drivers/gpu/drm/drm_irq.c:316: warning: Excess function parameter 'tv_ret' description in 'drm_accurate_vblank_count'
include/drm/drmP.h:168: warning: No description found for parameter 'fmt' include/drm/drmP.h:184: warning: No description found for parameter 'fmt' include/drm/drmP.h:202: warning: No description found for parameter 'fmt' include/drm/drmP.h:247: warning: No description found for parameter 'dev' include/drm/drmP.h:247: warning: No description found for parameter 'data' include/drm/drmP.h:247: warning: No description found for parameter 'file_priv' include/drm/drmP.h:280: warning: No description found for parameter 'ioctl' include/drm/drmP.h:280: warning: No description found for parameter '_func' include/drm/drmP.h:280: warning: No description found for parameter '_flags' include/drm/drmP.h:362: warning: cannot understand function prototype: 'struct drm_lock_data ' include/drm/drmP.h:415: warning: cannot understand function prototype: 'struct drm_driver ' include/drm/drmP.h:672: warning: cannot understand function prototype: 'struct drm_info_list ' include/drm/drmP.h:682: warning: cannot understand function prototype: 'struct drm_info_node ' include/drm/drmP.h:692: warning: cannot understand function prototype: 'struct drm_minor ' include/drm/drmP.h:740: warning: cannot understand function prototype: 'struct drm_device ' drivers/gpu/drm/i915/intel_runtime_pm.c:2275: warning: No description found for parameter 'resume' drivers/gpu/drm/i915/intel_runtime_pm.c:2275: warning: No description found for parameter 'resume' drivers/gpu/drm/i915/i915_irq.c:2663: warning: No description found for parameter 'fmt' drivers/gpu/drm/i915/i915_irq.c:2663: warning: No description found for parameter 'fmt' drivers/gpu/drm/i915/i915_irq.c:2663: warning: No description found for parameter 'fmt' drivers/gpu/drm/i915/i915_irq.c:2663: warning: No description found for parameter 'fmt' drivers/gpu/drm/i915/i915_gem.c:421: warning: No description found for parameter 'dev' drivers/gpu/drm/i915/i915_gem.c:421: warning: No description found for parameter 'data' drivers/gpu/drm/i915/i915_gem.c:421: warning: No description found for parameter 'file' drivers/gpu/drm/i915/i915_gem.c:686: warning: No description found for parameter 'dev' drivers/gpu/drm/i915/i915_gem.c:686: warning: No description found for parameter 'data' drivers/gpu/drm/i915/i915_gem.c:686: warning: No description found for parameter 'file' drivers/gpu/drm/i915/i915_gem.c:767: warning: No description found for parameter 'dev' drivers/gpu/drm/i915/i915_gem.c:767: warning: No description found for parameter 'obj' drivers/gpu/drm/i915/i915_gem.c:767: warning: No description found for parameter 'args' drivers/gpu/drm/i915/i915_gem.c:767: warning: No description found for parameter 'file' drivers/gpu/drm/i915/i915_gem.c:1029: warning: No description found for parameter 'dev' drivers/gpu/drm/i915/i915_gem.c:1029: warning: No description found for parameter 'data' drivers/gpu/drm/i915/i915_gem.c:1029: warning: No description found for parameter 'file' drivers/gpu/drm/i915/i915_gem.c:1245: warning: No description found for parameter 'rps' drivers/gpu/drm/i915/i915_gem.c:1459: warning: No description found for parameter 'req' drivers/gpu/drm/i915/i915_gem.c:1494: warning: No description found for parameter 'obj' drivers/gpu/drm/i915/i915_gem.c:1494: warning: No description found for parameter 'readonly' drivers/gpu/drm/i915/i915_gem.c:1617: warning: No description found for parameter 'dev' drivers/gpu/drm/i915/i915_gem.c:1617: warning: No description found for parameter 'data' drivers/gpu/drm/i915/i915_gem.c:1617: warning: No description found for parameter 'file' drivers/gpu/drm/i915/i915_gem.c:1680: warning: No description found for parameter 'dev' drivers/gpu/drm/i915/i915_gem.c:1680: warning: No description found for parameter 'data' drivers/gpu/drm/i915/i915_gem.c:1680: warning: No description found for parameter 'file' drivers/gpu/drm/i915/i915_gem.c:1725: warning: No description found for parameter 'dev' drivers/gpu/drm/i915/i915_gem.c:1725: warning: No description found for parameter 'data' drivers/gpu/drm/i915/i915_gem.c:1725: warning: No description found for parameter 'file' drivers/gpu/drm/i915/i915_gem.c:2013: warning: No description found for parameter 'dev' drivers/gpu/drm/i915/i915_gem.c:2013: warning: No description found for parameter 'size' drivers/gpu/drm/i915/i915_gem.c:2013: warning: No description found for parameter 'tiling_mode' drivers/gpu/drm/i915/i915_gem.c:2013: warning: No description found for parameter 'fenced' drivers/gpu/drm/i915/i915_gem.c:2013: warning: Excess function parameter 'obj' description in 'i915_gem_get_gtt_alignment' drivers/gpu/drm/i915/i915_gem.c:2911: warning: No description found for parameter 'engine' drivers/gpu/drm/i915/i915_gem.c:3037: warning: No description found for parameter 'obj' drivers/gpu/drm/i915/i915_gem.c:3087: warning: No description found for parameter 'dev' drivers/gpu/drm/i915/i915_gem.c:3087: warning: No description found for parameter 'data' drivers/gpu/drm/i915/i915_gem.c:3087: warning: No description found for parameter 'file' drivers/gpu/drm/i915/i915_gem.c:3087: warning: Excess function parameter 'DRM_IOCTL_ARGS' description in 'i915_gem_wait_ioctl' drivers/gpu/drm/i915/i915_gem.c:3459: warning: No description found for parameter 'obj' drivers/gpu/drm/i915/i915_gem.c:3459: warning: No description found for parameter 'vm' drivers/gpu/drm/i915/i915_gem.c:3459: warning: No description found for parameter 'ggtt_view' drivers/gpu/drm/i915/i915_gem.c:3459: warning: No description found for parameter 'alignment' drivers/gpu/drm/i915/i915_gem.c:3459: warning: No description found for parameter 'flags' drivers/gpu/drm/i915/i915_gem.c:3714: warning: No description found for parameter 'obj' drivers/gpu/drm/i915/i915_gem.c:3714: warning: No description found for parameter 'write' drivers/gpu/drm/i915/i915_gem.c:3789: warning: No description found for parameter 'obj' drivers/gpu/drm/i915/i915_gem.c:3789: warning: No description found for parameter 'cache_level' drivers/gpu/drm/i915/i915_gem.c:4063: warning: No description found for parameter 'obj' drivers/gpu/drm/i915/i915_gem.c:4063: warning: No description found for parameter 'write' drivers/gpu/drm/i915/i915_cmd_parser.c:748: warning: No description found for parameter 'engine' drivers/gpu/drm/i915/i915_cmd_parser.c:748: warning: Excess function parameter 'ring' description in 'i915_cmd_parser_init_ring' drivers/gpu/drm/i915/i915_cmd_parser.c:838: warning: No description found for parameter 'engine' drivers/gpu/drm/i915/i915_cmd_parser.c:838: warning: Excess function parameter 'ring' description in 'i915_cmd_parser_fini_ring' drivers/gpu/drm/i915/i915_cmd_parser.c:1034: warning: No description found for parameter 'engine' drivers/gpu/drm/i915/i915_cmd_parser.c:1034: warning: Excess function parameter 'ring' description in 'i915_needs_cmd_parser' drivers/gpu/drm/i915/i915_cmd_parser.c:1186: warning: No description found for parameter 'engine' drivers/gpu/drm/i915/i915_cmd_parser.c:1186: warning: Excess function parameter 'ring' description in 'i915_parse_cmds' drivers/gpu/drm/i915/i915_cmd_parser.c:748: warning: No description found for parameter 'engine' drivers/gpu/drm/i915/i915_cmd_parser.c:748: warning: Excess function parameter 'ring' description in 'i915_cmd_parser_init_ring' drivers/gpu/drm/i915/i915_cmd_parser.c:838: warning: No description found for parameter 'engine' drivers/gpu/drm/i915/i915_cmd_parser.c:838: warning: Excess function parameter 'ring' description in 'i915_cmd_parser_fini_ring' drivers/gpu/drm/i915/i915_cmd_parser.c:1034: warning: No description found for parameter 'engine' drivers/gpu/drm/i915/i915_cmd_parser.c:1034: warning: Excess function parameter 'ring' description in 'i915_needs_cmd_parser' drivers/gpu/drm/i915/i915_cmd_parser.c:1186: warning: No description found for parameter 'engine' drivers/gpu/drm/i915/i915_cmd_parser.c:1186: warning: Excess function parameter 'ring' description in 'i915_parse_cmds' drivers/gpu/drm/i915/intel_lrc.c:318: warning: No description found for parameter 'engine' drivers/gpu/drm/i915/intel_lrc.c:318: warning: Excess function parameter 'ring' description in 'intel_lr_context_descriptor_update' drivers/gpu/drm/i915/intel_lrc.c:355: warning: No description found for parameter 'engine' drivers/gpu/drm/i915/intel_lrc.c:355: warning: Excess function parameter 'ring' description in 'intel_execlists_ctx_id' drivers/gpu/drm/i915/intel_lrc.c:547: warning: No description found for parameter 'engine' drivers/gpu/drm/i915/intel_lrc.c:547: warning: Excess function parameter 'ring' description in 'intel_lrc_irq_handler' drivers/gpu/drm/i915/intel_lrc.c:951: warning: No description found for parameter 'params' drivers/gpu/drm/i915/intel_lrc.c:951: warning: Excess function parameter 'dev' description in 'intel_execlists_submission' drivers/gpu/drm/i915/intel_lrc.c:951: warning: Excess function parameter 'file' description in 'intel_execlists_submission' drivers/gpu/drm/i915/intel_lrc.c:951: warning: Excess function parameter 'ring' description in 'intel_execlists_submission' drivers/gpu/drm/i915/intel_lrc.c:951: warning: Excess function parameter 'ctx' description in 'intel_execlists_submission' drivers/gpu/drm/i915/intel_lrc.c:951: warning: Excess function parameter 'batch_obj' description in 'intel_execlists_submission' drivers/gpu/drm/i915/intel_lrc.c:951: warning: Excess function parameter 'exec_start' description in 'intel_execlists_submission' drivers/gpu/drm/i915/intel_lrc.c:951: warning: Excess function parameter 'dispatch_flags' description in 'intel_execlists_submission' drivers/gpu/drm/i915/intel_lrc.c:1334: warning: No description found for parameter 'engine'
vim +316 drivers/gpu/drm/drm_irq.c
170 * 171 * Note: caller must hold dev->vbl_lock since this reads & writes 172 * device vblank fields. 173 */ 174 static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, 175 unsigned long flags)
176 {
177 struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; 178 u32 cur_vblank, diff; 179 bool rc; 180 struct timeval t_vblank; 181 int count = DRM_TIMESTAMP_MAXRETRIES; 182 int framedur_ns = vblank->framedur_ns; 183 184 /* 185 * Interrupts were disabled prior to this call, so deal with counter 186 * wrap if needed. 187 * NOTE! It's possible we lost a full dev->max_vblank_count + 1 events 188 * here if the register is small or we had vblank interrupts off for 189 * a long time. 190 * 191 * We repeat the hardware vblank counter & timestamp query until 192 * we get consistent results. This to prevent races between gpu 193 * updating its hardware counter while we are retrieving the 194 * corresponding vblank timestamp. 195 */ 196 do { 197 cur_vblank = dev->driver->get_vblank_counter(dev, pipe); 198 rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, flags); 199 } while (cur_vblank != dev->driver->get_vblank_counter(dev, pipe) && --count > 0); 200 201 if (dev->max_vblank_count != 0) { 202 /* trust the hw counter when it's around */ 203 diff = (cur_vblank - vblank->last) & dev->max_vblank_count; 204 } else if (rc && framedur_ns) { 205 const struct timeval *t_old; 206 u64 diff_ns; 207 208 t_old = &vblanktimestamp(dev, pipe, vblank->count); 209 diff_ns = timeval_to_ns(&t_vblank) - timeval_to_ns(t_old); 210 211 /* 212 * Figure out how many vblanks we've missed based 213 * on the difference in the timestamps and the 214 * frame/field duration. 215 */ 216 diff = DIV_ROUND_CLOSEST_ULL(diff_ns, framedur_ns); 217 218 if (diff == 0 && flags & DRM_CALLED_FROM_VBLIRQ) 219 DRM_DEBUG_VBL("crtc %u: Redundant vblirq ignored." 220 " diff_ns = %lld, framedur_ns = %d)\n", 221 pipe, (long long) diff_ns, framedur_ns); 222 } else { 223 /* some kind of default for drivers w/o accurate vbl timestamping */ 224 diff = (flags & DRM_CALLED_FROM_VBLIRQ) != 0; 225 } 226 227 /* 228 * Within a drm_vblank_pre_modeset - drm_vblank_post_modeset 229 * interval? If so then vblank irqs keep running and it will likely 230 * happen that the hardware vblank counter is not trustworthy as it 231 * might reset at some point in that interval and vblank timestamps 232 * are not trustworthy either in that interval. Iow. this can result 233 * in a bogus diff >> 1 which must be avoided as it would cause 234 * random large forward jumps of the software vblank counter. 235 */ 236 if (diff > 1 && (vblank->inmodeset & 0x2)) { 237 DRM_DEBUG_VBL("clamping vblank bump to 1 on crtc %u: diffr=%u" 238 " due to pre-modeset.\n", pipe, diff); 239 diff = 1; 240 } 241 242 /* 243 * FIMXE: Need to replace this hack with proper seqlocks. 244 * 245 * Restrict the bump of the software vblank counter to a safe maximum 246 * value of +1 whenever there is the possibility that concurrent readers 247 * of vblank timestamps could be active at the moment, as the current 248 * implementation of the timestamp caching and updating is not safe 249 * against concurrent readers for calls to store_vblank() with a bump 250 * of anything but +1. A bump != 1 would very likely return corrupted 251 * timestamps to userspace, because the same slot in the cache could 252 * be concurrently written by store_vblank() and read by one of those 253 * readers without the read-retry logic detecting the collision. 254 * 255 * Concurrent readers can exist when we are called from the 256 * drm_vblank_off() or drm_vblank_on() functions and other non-vblank- 257 * irq callers. However, all those calls to us are happening with the 258 * vbl_lock locked to prevent drm_vblank_get(), so the vblank refcount 259 * can't increase while we are executing. Therefore a zero refcount at 260 * this point is safe for arbitrary counter bumps if we are called 261 * outside vblank irq, a non-zero count is not 100% safe. Unfortunately 262 * we must also accept a refcount of 1, as whenever we are called from 263 * drm_vblank_get() -> drm_vblank_enable() the refcount will be 1 and 264 * we must let that one pass through in order to not lose vblank counts 265 * during vblank irq off - which would completely defeat the whole 266 * point of this routine. 267 * 268 * Whenever we are called from vblank irq, we have to assume concurrent 269 * readers exist or can show up any time during our execution, even if 270 * the refcount is currently zero, as vblank irqs are usually only 271 * enabled due to the presence of readers, and because when we are called 272 * from vblank irq we can't hold the vbl_lock to protect us from sudden 273 * bumps in vblank refcount. Therefore also restrict bumps to +1 when 274 * called from vblank irq. 275 */ 276 if ((diff > 1) && (atomic_read(&vblank->refcount) > 1 || 277 (flags & DRM_CALLED_FROM_VBLIRQ))) { 278 DRM_DEBUG_VBL("clamping vblank bump to 1 on crtc %u: diffr=%u " 279 "refcount %u, vblirq %u\n", pipe, diff, 280 atomic_read(&vblank->refcount), 281 (flags & DRM_CALLED_FROM_VBLIRQ) != 0); 282 diff = 1; 283 } 284 285 DRM_DEBUG_VBL("updating vblank count on crtc %u:" 286 " current=%u, diff=%u, hw=%u hw_last=%u\n", 287 pipe, vblank->count, diff, cur_vblank, vblank->last); 288 289 if (diff == 0) { 290 WARN_ON_ONCE(cur_vblank != vblank->last); 291 return; 292 } 293 294 /* 295 * Only reinitialize corresponding vblank timestamp if high-precision query 296 * available and didn't fail, or we were called from the vblank interrupt. 297 * Otherwise reinitialize delayed at next vblank interrupt and assign 0 298 * for now, to mark the vblanktimestamp as invalid. 299 */ 300 if (!rc && (flags & DRM_CALLED_FROM_VBLIRQ) == 0) 301 t_vblank = (struct timeval) {0, 0}; 302 303 store_vblank(dev, pipe, diff, &t_vblank, cur_vblank); 304 } 305 306 /** 307 * drm_accurate_vblank_count - retrieve the master vblank counter 308 * @crtc: which counter to retrieve 309 * @tv_ret: last time counter was updated 310 * 311 * This function is similar to @drm_crtc_vblank_count but this 312 * function interpolates to handle a race with vblank irq's. 313 */ 314 315 u32 drm_accurate_vblank_count(struct drm_crtc *crtc)
316 {
317 struct drm_device *dev = crtc->dev; 318 u32 vblank, pipe = drm_crtc_index(crtc); 319 unsigned long flags;
--- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
dri-devel@lists.freedesktop.org