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 <wxiaowen@codeaurora.org>
Signed-off-by: Samantha Tran <samtran@codeaurora.org>
此提交包含在:
Xiaowen Wu
2019-08-01 10:15:33 -07:00
提交者 Samantha Tran
父節點 ed6f9809d2
當前提交 8f99559493
共有 2 個檔案被更改,包括 8 行新增1 行删除

查看文件

@@ -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);