From 8f99559493867bb823b9f807e7df75b9322b51c6 Mon Sep 17 00:00:00 2001 From: Xiaowen Wu Date: Thu, 1 Aug 2019 10:15:33 -0700 Subject: [PATCH] disp: msm: fix re-entry problem for msm_atomic_commit When plane is detached from crtc in one atomic commit and then attached to another crtc in the next atomic commit, the second plane state swap will happen when the first commit is still running in the previous crtc's worker thread, which will result in two threads programming the same plane and run into undeterministic state. Fix is to add plane_mask check before state swap, together with crtc_mask check. This will make sure there is no pending worker thread working on the same plane. Change-Id: I64cd4b68fa9746e988d933069ac0f8083d974c79 Signed-off-by: Xiaowen Wu Signed-off-by: Samantha Tran --- msm/msm_atomic.c | 8 +++++++- msm/msm_drv.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/msm/msm_atomic.c b/msm/msm_atomic.c index 5bdb37bacd..c345179b9b 100644 --- a/msm/msm_atomic.c +++ b/msm/msm_atomic.c @@ -28,6 +28,7 @@ struct msm_commit { struct drm_device *dev; struct drm_atomic_state *state; uint32_t crtc_mask; + uint32_t plane_mask; bool nonblock; struct kthread_work commit_work; }; @@ -104,11 +105,13 @@ static void commit_destroy(struct msm_commit *c) { struct msm_drm_private *priv = c->dev->dev_private; uint32_t crtc_mask = c->crtc_mask; + uint32_t plane_mask = c->plane_mask; /* End_atomic */ spin_lock(&priv->pending_crtcs_event.lock); DBG("end: %08x", crtc_mask); priv->pending_crtcs &= ~crtc_mask; + priv->pending_planes &= ~plane_mask; wake_up_all_locked(&priv->pending_crtcs_event); spin_unlock(&priv->pending_crtcs_event.lock); @@ -713,6 +716,7 @@ int msm_atomic_commit(struct drm_device *dev, drm_atomic_set_fence_for_plane(new_plane_state, fence); } + c->plane_mask |= (1 << drm_plane_index(plane)); } /* @@ -723,10 +727,12 @@ int msm_atomic_commit(struct drm_device *dev, /* Start Atomic */ spin_lock(&priv->pending_crtcs_event.lock); ret = wait_event_interruptible_locked(priv->pending_crtcs_event, - !(priv->pending_crtcs & c->crtc_mask)); + !(priv->pending_crtcs & c->crtc_mask) && + !(priv->pending_planes & c->plane_mask)); if (ret == 0) { DBG("start: %08x", c->crtc_mask); priv->pending_crtcs |= c->crtc_mask; + priv->pending_planes |= c->plane_mask; } spin_unlock(&priv->pending_crtcs_event.lock); diff --git a/msm/msm_drv.h b/msm/msm_drv.h index d4b8df59fb..1cf63841aa 100644 --- a/msm/msm_drv.h +++ b/msm/msm_drv.h @@ -631,6 +631,7 @@ struct msm_drm_private { /* crtcs pending async atomic updates: */ uint32_t pending_crtcs; + uint32_t pending_planes; wait_queue_head_t pending_crtcs_event; unsigned int num_planes;