[PATCH] drm/vblank: Fix race between drm_crtc_arm_vblank_event() and the irq

ville.syrjala at linux.intel.com ville.syrjala at linux.intel.com
Fri Jun 30 12:27:29 UTC 2017


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

Make sure the armed even doesn't fire until the next vblank by adding
one to the current vblank counter value. This will prevent the event
being fired off prematurely if drm_handle_vblank() is called
redundantly, or if the irq handler gets delayed somehow.

This is actually a real race on Intel gen2/3 hardware due to the vblank
interrupt firing approx. one or more scanlines after the start of vblank
(which is when the double buffered registers get latched). So if we were
to perform an atomic update just after the start of vblank, but before
the irq has fired, the irq handler would send out the the event immediately
instead of waiting for the next vblank like it should.

This also makes logs less confusing because now it normally looks like
the vblank interrupt was somehow missed and the event gets sent one
frame too late.

Cc: Daniel Vetter <daniel at ffwll.ch>
Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
---
 drivers/gpu/drm/drm_vblank.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c
index bfe86fa2d3b1..823c853de052 100644
--- a/drivers/gpu/drm/drm_vblank.c
+++ b/drivers/gpu/drm/drm_vblank.c
@@ -869,7 +869,7 @@ void drm_crtc_arm_vblank_event(struct drm_crtc *crtc,
 	assert_spin_locked(&dev->event_lock);
 
 	e->pipe = pipe;
-	e->event.sequence = drm_vblank_count(dev, pipe);
+	e->event.sequence = drm_vblank_count(dev, pipe) + 1;
 	e->event.crtc_id = crtc->base.id;
 	list_add_tail(&e->base.link, &dev->vblank_event_list);
 }
-- 
2.13.0



More information about the dri-devel mailing list