소스 검색

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