瀏覽代碼

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 <[email protected]>
Yashwanth 4 年之前
父節點
當前提交
75f3403326
共有 3 個文件被更改,包括 7 次插入1 次删除
  1. 3 0
      msm/sde/sde_crtc.c
  2. 2 0
      msm/sde/sde_crtc.h
  3. 2 1
      msm/sde/sde_encoder.c

+ 3 - 0
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;

+ 2 - 0
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];

+ 2 - 1
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);