فهرست منبع

disp: msm: sde: fix handling the missing pp-done interrupt cases

With posted-start, ctl scheduler status and pending-kickoff
count are checked to address the missing pp-done interrupt
cases, which can occur if the IRQs are disabled for a long
time by some entity. Currently this check is done after
the wr-ptr-irq. At this point the scheduler status may
or may not be idle, based on the frame-transfer. Move this
handling after the timeout, so the scheduler is guaranteed
to be in idle state for working use-case.

Change-Id: I3fa9ecce8139ff667c1882e286571169c543c797
Signed-off-by: Veera Sundaram Sankaran <[email protected]>
Veera Sundaram Sankaran 5 سال پیش
والد
کامیت
e167ae786c
1فایلهای تغییر یافته به همراه39 افزوده شده و 15 حذف شده
  1. 39 15
      msm/sde/sde_encoder_phys_cmd.c

+ 39 - 15
msm/sde/sde_encoder_phys_cmd.c

@@ -663,28 +663,23 @@ static bool _sde_encoder_phys_cmd_is_ongoing_pptx(
 	return false;
 }
 
-static int _sde_encoder_phys_cmd_wait_for_idle(
+static bool _sde_encoder_phys_cmd_is_scheduler_idle(
 		struct sde_encoder_phys *phys_enc)
 {
-	struct sde_encoder_phys_cmd *cmd_enc =
-			to_sde_encoder_phys_cmd(phys_enc);
-	struct sde_encoder_wait_info wait_info = {0};
-	bool recovery_events;
-	int ret;
-	struct sde_hw_ctl *ctl;
 	bool wr_ptr_wait_success = true;
 	unsigned long lock_flags;
-
-	if (!phys_enc) {
-		SDE_ERROR("invalid encoder\n");
-		return -EINVAL;
-	}
-
-	ctl = phys_enc->hw_ctl;
+	bool ret = false;
+	struct sde_encoder_phys_cmd *cmd_enc =
+			to_sde_encoder_phys_cmd(phys_enc);
+	struct sde_hw_ctl *ctl = phys_enc->hw_ctl;
 
 	if (sde_encoder_phys_cmd_is_master(phys_enc))
 		wr_ptr_wait_success = cmd_enc->wr_ptr_wait_success;
 
+	/*
+	 * Handle cases where a pp-done interrupt is missed
+	 * due to irq latency with POSTED start
+	 */
 	if (wr_ptr_wait_success &&
 	    (phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_POSTED_START) &&
 	    ctl->ops.get_scheduler_status &&
@@ -698,7 +693,30 @@ static int _sde_encoder_phys_cmd_wait_for_idle(
 			SDE_ENCODER_FRAME_EVENT_DONE |
 			SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE);
 		spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags);
-		return 0;
+
+		SDE_EVT32(DRMID(phys_enc->parent),
+			phys_enc->hw_pp->idx - PINGPONG_0,
+			phys_enc->hw_intf->idx - INTF_0,
+			atomic_read(&phys_enc->pending_kickoff_cnt));
+
+		ret = true;
+	}
+
+	return ret;
+}
+
+static int _sde_encoder_phys_cmd_wait_for_idle(
+		struct sde_encoder_phys *phys_enc)
+{
+	struct sde_encoder_phys_cmd *cmd_enc =
+			to_sde_encoder_phys_cmd(phys_enc);
+	struct sde_encoder_wait_info wait_info = {0};
+	bool recovery_events;
+	int ret;
+
+	if (!phys_enc) {
+		SDE_ERROR("invalid encoder\n");
+		return -EINVAL;
 	}
 
 	if (atomic_read(&phys_enc->pending_kickoff_cnt) > 1)
@@ -714,9 +732,15 @@ static int _sde_encoder_phys_cmd_wait_for_idle(
 	if (_sde_encoder_phys_is_ppsplit_slave(phys_enc))
 		return 0;
 
+	if (_sde_encoder_phys_cmd_is_scheduler_idle(phys_enc))
+		return 0;
+
 	ret = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_PINGPONG,
 			&wait_info);
 	if (ret == -ETIMEDOUT) {
+		if (_sde_encoder_phys_cmd_is_scheduler_idle(phys_enc))
+			return 0;
+
 		_sde_encoder_phys_cmd_handle_ppdone_timeout(phys_enc,
 				recovery_events);
 	} else if (!ret) {