summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/vkms/vkms_crc.c27
-rw-r--r--drivers/gpu/drm/vkms/vkms_crtc.c9
-rw-r--r--drivers/gpu/drm/vkms/vkms_drv.h2
3 files changed, 22 insertions, 16 deletions
diff --git a/drivers/gpu/drm/vkms/vkms_crc.c b/drivers/gpu/drm/vkms/vkms_crc.c
index e66ff25c008e..e9fb4ebb789f 100644
--- a/drivers/gpu/drm/vkms/vkms_crc.c
+++ b/drivers/gpu/drm/vkms/vkms_crc.c
@@ -166,16 +166,24 @@ void vkms_crc_work_handle(struct work_struct *work)
struct drm_plane *plane;
u32 crc32 = 0;
u64 frame_start, frame_end;
+ bool crc_pending;
unsigned long flags;
spin_lock_irqsave(&out->state_lock, flags);
frame_start = crtc_state->frame_start;
frame_end = crtc_state->frame_end;
+ crc_pending = crtc_state->crc_pending;
+ crtc_state->frame_start = 0;
+ crtc_state->frame_end = 0;
+ crtc_state->crc_pending = false;
spin_unlock_irqrestore(&out->state_lock, flags);
- /* _vblank_handle() hasn't updated frame_start yet */
- if (!frame_start || frame_start == frame_end)
- goto out;
+ /*
+ * We raced with the vblank hrtimer and previous work already computed
+ * the crc, nothing to do.
+ */
+ if (!crc_pending)
+ return;
drm_for_each_plane(plane, &vdev->drm) {
struct vkms_plane_state *vplane_state;
@@ -196,20 +204,11 @@ void vkms_crc_work_handle(struct work_struct *work)
if (primary_crc)
crc32 = _vkms_get_crc(primary_crc, cursor_crc);
- frame_end = drm_crtc_accurate_vblank_count(crtc);
-
- /* queue_work can fail to schedule crc_work; add crc for
- * missing frames
+ /*
+ * The worker can fall behind the vblank hrtimer, make sure we catch up.
*/
while (frame_start <= frame_end)
drm_crtc_add_crc_entry(crtc, true, frame_start++, &crc32);
-
-out:
- /* to avoid using the same value for frame number again */
- spin_lock_irqsave(&out->state_lock, flags);
- crtc_state->frame_end = frame_end;
- crtc_state->frame_start = 0;
- spin_unlock_irqrestore(&out->state_lock, flags);
}
static const char * const pipe_crc_sources[] = {"auto"};
diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_crtc.c
index 4d11292bc6f3..f392fa13015b 100644
--- a/drivers/gpu/drm/vkms/vkms_crtc.c
+++ b/drivers/gpu/drm/vkms/vkms_crtc.c
@@ -30,13 +30,18 @@ static enum hrtimer_restart vkms_vblank_simulate(struct hrtimer *timer)
* has read the data
*/
spin_lock(&output->state_lock);
- if (!state->frame_start)
+ if (!state->crc_pending)
state->frame_start = frame;
+ else
+ DRM_DEBUG_DRIVER("crc worker falling behind, frame_start: %llu, frame_end: %llu\n",
+ state->frame_start, frame);
+ state->frame_end = frame;
+ state->crc_pending = true;
spin_unlock(&output->state_lock);
ret = queue_work(output->crc_workq, &state->crc_work);
if (!ret)
- DRM_WARN("failed to queue vkms_crc_work_handle");
+ DRM_DEBUG_DRIVER("vkms_crc_work_handle already queued\n");
}
spin_unlock(&output->lock);
diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h
index b92c30c66a6f..2b37eb1062d3 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.h
+++ b/drivers/gpu/drm/vkms/vkms_drv.h
@@ -48,6 +48,8 @@ struct vkms_plane_state {
struct vkms_crtc_state {
struct drm_crtc_state base;
struct work_struct crc_work;
+
+ bool crc_pending;
u64 frame_start;
u64 frame_end;
};