aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Pinchart <[email protected]>2017-03-04 15:14:47 +0200
committerKieran Bingham <[email protected]>2017-05-22 16:11:41 +0100
commit7f53b19cdff78f696b61cd5987dfe1a5d432676b (patch)
tree4696d60807e57b00835294b014e5b6099c17e74d
parent2ea659a9ef488125eb46da6eb571de5eae5c43f6 (diff)
drm: rcar-du: Arm the page flip event after queuing the page flip
The page flip event is armed in the atomic begin handler, creating a race condition with the frame end interrupt that could send the event before the atomic operation actually completes. To avoid that, arm the event in the atomic flush handler after queuing the page flip. This change doesn't fully close the race window, as the frame end interrupt could be generated before the page flip is committed to hardware but only handled after the event is armed. However, the race window is now much smaller. Signed-off-by: Laurent Pinchart <[email protected]> Reviewed-by: Kieran Bingham <[email protected]> Signed-off-by: Kieran Bingham <[email protected]>
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_crtc.c22
1 files changed, 11 insertions, 11 deletions
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 4ed6f2340af0..5f0664bcd12d 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -581,17 +581,6 @@ static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc,
struct drm_crtc_state *old_crtc_state)
{
struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
- struct drm_device *dev = rcrtc->crtc.dev;
- unsigned long flags;
-
- if (crtc->state->event) {
- WARN_ON(drm_crtc_vblank_get(crtc) != 0);
-
- spin_lock_irqsave(&dev->event_lock, flags);
- rcrtc->event = crtc->state->event;
- crtc->state->event = NULL;
- spin_unlock_irqrestore(&dev->event_lock, flags);
- }
if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
rcar_du_vsp_atomic_begin(rcrtc);
@@ -601,9 +590,20 @@ static void rcar_du_crtc_atomic_flush(struct drm_crtc *crtc,
struct drm_crtc_state *old_crtc_state)
{
struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
+ struct drm_device *dev = rcrtc->crtc.dev;
+ unsigned long flags;
rcar_du_crtc_update_planes(rcrtc);
+ if (crtc->state->event) {
+ WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+
+ spin_lock_irqsave(&dev->event_lock, flags);
+ rcrtc->event = crtc->state->event;
+ crtc->state->event = NULL;
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+ }
+
if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
rcar_du_vsp_atomic_flush(rcrtc);
}