From 75f3403326762c192ab63c11d4dee4a3b91d435f Mon Sep 17 00:00:00 2001 From: Yashwanth Date: Wed, 13 Jan 2021 19:07:50 +0530 Subject: [PATCH] disp: msm: sde: add kickoff_in_progress flag in sde crtc In dual display usecases, during pm suspend/resume, commit is scheduled only on primary crtc thread. If idle timeout value is very short such as in LP2 mode, it might result in race condition due to idle pc off work getting scheduled on its crtc thread. This change adds kickoff in progress flag to handle such cases as crtc frame pending count is only updated after rc kickoff. Change-Id: Iebb331d914b23cc5eeadfeb2a488891e88b3202a Signed-off-by: Yashwanth --- msm/sde/sde_crtc.c | 3 +++ msm/sde/sde_crtc.h | 2 ++ msm/sde/sde_encoder.c | 3 ++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/msm/sde/sde_crtc.c b/msm/sde/sde_crtc.c index 129d02b958..be0fc090bb 100644 --- a/msm/sde/sde_crtc.c +++ b/msm/sde/sde_crtc.c @@ -3998,6 +3998,7 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc, idle_pc_state = sde_crtc_get_property(cstate, CRTC_PROP_IDLE_PC_STATE); + sde_crtc->kickoff_in_progress = true; list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { if (encoder->crtc != crtc) continue; @@ -4059,6 +4060,7 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc, sde_encoder_kickoff(encoder, false, true); } + sde_crtc->kickoff_in_progress = false; /* store the event after frame trigger */ if (sde_crtc->event) { @@ -7092,6 +7094,7 @@ struct drm_crtc *sde_crtc_init(struct drm_device *dev, struct drm_plane *plane) atomic_set(&sde_crtc->frame_pending, 0); sde_crtc->enabled = false; + sde_crtc->kickoff_in_progress = false; /* Below parameters are for fps calculation for sysfs node */ sde_crtc->fps_info.fps_periodic_duration = DEFAULT_FPS_PERIOD_1_SEC; diff --git a/msm/sde/sde_crtc.h b/msm/sde/sde_crtc.h index 3b7c1397cd..0697fcbaa8 100644 --- a/msm/sde/sde_crtc.h +++ b/msm/sde/sde_crtc.h @@ -286,6 +286,7 @@ struct sde_frame_data { * @ad_active : list containing ad properties that are active * @crtc_lock : crtc lock around create, destroy and access. * @frame_pending : Whether or not an update is pending + * @kickoff_in_progress : boolean entry to check if kickoff is in progress * @frame_events : static allocation of in-flight frame events * @frame_event_list : available frame event list * @spin_lock : spin lock for transaction status, etc... @@ -379,6 +380,7 @@ struct sde_crtc { struct list_head frame_event_list; spinlock_t spin_lock; spinlock_t fevent_spin_lock; + bool kickoff_in_progress; /* for handling internal event thread */ struct sde_crtc_event event_cache[SDE_CRTC_MAX_EVENT_COUNT]; diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index a50d36ad39..e53a1cc38b 100644 --- a/msm/sde/sde_encoder.c +++ b/msm/sde/sde_encoder.c @@ -2091,7 +2091,8 @@ static int _sde_encoder_rc_idle(struct drm_encoder *drm_enc, sw_event, sde_enc->rc_state); SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state, SDE_EVTLOG_ERROR); goto end; - } else if (sde_crtc_frame_pending(sde_enc->crtc)) { + } else if (sde_crtc_frame_pending(sde_enc->crtc) || + sde_crtc->kickoff_in_progress) { SDE_DEBUG_ENC(sde_enc, "skip idle entry"); SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state, sde_crtc_frame_pending(sde_enc->crtc), SDE_EVTLOG_ERROR);