When there are back to back commits with async cursor update,
there is a case where second commit can program the DPU hw
blocks while first didn't complete flushing config to HW.
Synchronize the compositions such that second commit waits
until first commit flushes the composition.
This change also introduces per crtc commit lock, such that
commits on different crtcs are not blocked by each other.
Signed-off-by: Krishna Manikandan <mkrishn@xxxxxxxxxxxxxx>
---
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 1 +
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h | 1 +
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 26
++++++++++++++++++++++++
drivers/gpu/drm/msm/msm_atomic.c | 35
++++++++++++++++++++++----------
drivers/gpu/drm/msm/msm_kms.h | 5 +++++
5 files changed, 57 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index c2729f7..9024719 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -1383,6 +1383,7 @@ struct drm_crtc *dpu_crtc_init(struct drm_device
*dev, struct drm_plane *plane,
/* initialize event handling */
spin_lock_init(&dpu_crtc->event_lock);
+ mutex_init(&dpu_crtc->commit_lock);
DPU_DEBUG("%s: successfully initialized crtc\n",
dpu_crtc->name);
return crtc;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
index cec3474..1eeb73d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
@@ -169,6 +169,7 @@ struct dpu_crtc {
/* for handling internal event thread */
spinlock_t event_lock;
+ struct mutex commit_lock;
struct dpu_core_perf_params cur_perf;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index c0a4d4e..f99ae7a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -445,6 +445,30 @@ static void dpu_kms_wait_flush(struct msm_kms
*kms, unsigned crtc_mask)
dpu_kms_wait_for_commit_done(kms, crtc);
}
+static void dpu_kms_commit_lock(struct msm_kms *kms, unsigned int
crtc_mask)
+{
+ struct dpu_kms *dpu_kms = to_dpu_kms(kms);
+ struct drm_crtc *crtc;
+ struct dpu_crtc *dpu_crtc;
+
+ for_each_crtc_mask(dpu_kms->dev, crtc, crtc_mask) {
+ dpu_crtc = to_dpu_crtc(crtc);
+ mutex_lock(&dpu_crtc->commit_lock);
+ }
+}
+
+static void dpu_kms_commit_unlock(struct msm_kms *kms, unsigned int
crtc_mask)
+{
+ struct dpu_kms *dpu_kms = to_dpu_kms(kms);
+ struct drm_crtc *crtc;
+ struct dpu_crtc *dpu_crtc;
+
+ for_each_crtc_mask(dpu_kms->dev, crtc, crtc_mask) {
+ dpu_crtc = to_dpu_crtc(crtc);
+ mutex_unlock(&dpu_crtc->commit_lock);
+ }
+}
+
static int _dpu_kms_initialize_dsi(struct drm_device *dev,
struct msm_drm_private *priv,
struct dpu_kms *dpu_kms)
@@ -738,6 +762,8 @@ static const struct msm_kms_funcs kms_funcs = {
#ifdef CONFIG_DEBUG_FS
.debugfs_init = dpu_kms_debugfs_init,
#endif
+ .commit_lock = dpu_kms_commit_lock,
+ .commit_unlock = dpu_kms_commit_unlock,
};
static void _dpu_kms_mmu_destroy(struct dpu_kms *dpu_kms)
diff --git a/drivers/gpu/drm/msm/msm_atomic.c
b/drivers/gpu/drm/msm/msm_atomic.c
index 561bfa4..d33253f 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -55,16 +55,32 @@ static void vblank_put(struct msm_kms *kms,
unsigned crtc_mask)
}
}
+static void msm_commit_lock(struct msm_kms *kms, unsigned int
crtc_mask)
+{
+ if (kms->funcs->commit_lock)
+ kms->funcs->commit_lock(kms, crtc_mask);
+ else
+ mutex_lock(&kms->commit_lock);
+}
+
+static void msm_commit_unlock(struct msm_kms *kms, unsigned int
crtc_mask)
+{
+ if (kms->funcs->commit_unlock)
+ kms->funcs->commit_unlock(kms, crtc_mask);
+ else
+ mutex_unlock(&kms->commit_lock);
+}