Pārlūkot izejas kodu

disp: msm: sde: wait for specific pp_done instead of zero

2 Frames transfer pending is possible with posted start.
One ongoing frame and another triggered frame. Current SW
waits for pp_done interrupt if pending frame count is greater
than 1. It is possible that interrupt may be missed for ongoing
frame. In that case, SW should run pp_done wait for one by one
frame instead of two frames together. It allows encoder to
check the ctl scheduler status and trigger the frame done
event on time.

Change-Id: I4817842292d96747890ee70da8a5bdf9b56816ed
Signed-off-by: Dhaval Patel <[email protected]>
Dhaval Patel 5 gadi atpakaļ
vecāks
revīzija
6f06e5cd6f

+ 6 - 3
msm/sde/sde_encoder.c

@@ -408,13 +408,16 @@ static int _sde_encoder_wait_timeout(int32_t drm_id, int32_t hw_id,
 
 	do {
 		rc = wait_event_timeout(*(info->wq),
-			atomic_read(info->atomic_cnt) == 0, wait_time_jiffies);
+			atomic_read(info->atomic_cnt) == info->count_check,
+			wait_time_jiffies);
 		cur_ktime = ktime_get();
 
 		SDE_EVT32(drm_id, hw_id, rc, ktime_to_ms(cur_ktime),
-			timeout_ms, atomic_read(info->atomic_cnt));
+			timeout_ms, atomic_read(info->atomic_cnt),
+			info->count_check);
 	/* If we timed out, counter is valid and time is less, wait again */
-	} while (atomic_read(info->atomic_cnt) && (rc == 0) &&
+	} while ((atomic_read(info->atomic_cnt) != info->count_check) &&
+			(rc == 0) &&
 			(ktime_compare_safe(exp_ktime, cur_ktime) > 0));
 
 	return rc;

+ 2 - 0
msm/sde/sde_encoder_phys.h

@@ -458,11 +458,13 @@ struct sde_enc_phys_init_params {
  * sde_encoder_wait_info - container for passing arguments to irq wait functions
  * @wq: wait queue structure
  * @atomic_cnt: wait until atomic_cnt equals zero
+ * @count_check: wait for specific atomic_cnt instead of zero.
  * @timeout_ms: timeout value in milliseconds
  */
 struct sde_encoder_wait_info {
 	wait_queue_head_t *wq;
 	atomic_t *atomic_cnt;
+	u32 count_check;
 	s64 timeout_ms;
 };
 

+ 14 - 5
msm/sde/sde_encoder_phys_cmd.c

@@ -647,10 +647,11 @@ static int _sde_encoder_phys_cmd_wait_for_idle(
 {
 	struct sde_encoder_phys_cmd *cmd_enc =
 			to_sde_encoder_phys_cmd(phys_enc);
-	struct sde_encoder_wait_info wait_info;
+	struct sde_encoder_wait_info wait_info = {0};
 	bool recovery_events;
 	int ret;
 	struct sde_hw_ctl *ctl;
+	bool wr_ptr_wait_success = true;
 
 	if (!phys_enc) {
 		SDE_ERROR("invalid encoder\n");
@@ -658,7 +659,11 @@ static int _sde_encoder_phys_cmd_wait_for_idle(
 	}
 
 	ctl = phys_enc->hw_ctl;
-	if (cmd_enc->wr_ptr_wait_success &&
+
+	if (sde_encoder_phys_cmd_is_master(phys_enc))
+		wr_ptr_wait_success = cmd_enc->wr_ptr_wait_success;
+
+	if (wr_ptr_wait_success &&
 	    (phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_POSTED_START) &&
 	    ctl->ops.get_scheduler_status &&
 	    (ctl->ops.get_scheduler_status(ctl) & BIT(0)) &&
@@ -672,6 +677,9 @@ static int _sde_encoder_phys_cmd_wait_for_idle(
 		return 0;
 	}
 
+	if (atomic_read(&phys_enc->pending_kickoff_cnt) > 1)
+		wait_info.count_check = 1;
+
 	wait_info.wq = &phys_enc->pending_kickoff_wq;
 	wait_info.atomic_cnt = &phys_enc->pending_kickoff_cnt;
 	wait_info.timeout_ms = KICKOFF_TIMEOUT_MS;
@@ -707,7 +715,7 @@ static int _sde_encoder_phys_cmd_wait_for_autorefresh_done(
 {
 	struct sde_encoder_phys_cmd *cmd_enc =
 			to_sde_encoder_phys_cmd(phys_enc);
-	struct sde_encoder_wait_info wait_info;
+	struct sde_encoder_wait_info wait_info = {0};
 	int ret = 0;
 
 	if (!phys_enc) {
@@ -1334,7 +1342,7 @@ static int _sde_encoder_phys_cmd_wait_for_wr_ptr(
 {
 	struct sde_encoder_phys_cmd *cmd_enc =
 			to_sde_encoder_phys_cmd(phys_enc);
-	struct sde_encoder_wait_info wait_info;
+	struct sde_encoder_wait_info wait_info = {0};
 	int ret;
 	bool frame_pending = true;
 	struct sde_hw_ctl *ctl;
@@ -1383,6 +1391,7 @@ static int _sde_encoder_phys_cmd_wait_for_wr_ptr(
 	}
 
 	cmd_enc->wr_ptr_wait_success = (ret == 0) ? true : false;
+
 	return ret;
 }
 
@@ -1461,7 +1470,7 @@ static int sde_encoder_phys_cmd_wait_for_vblank(
 {
 	int rc = 0;
 	struct sde_encoder_phys_cmd *cmd_enc;
-	struct sde_encoder_wait_info wait_info;
+	struct sde_encoder_wait_info wait_info = {0};
 
 	if (!phys_enc)
 		return -EINVAL;

+ 1 - 1
msm/sde/sde_encoder_phys_vid.c

@@ -864,7 +864,7 @@ static void sde_encoder_phys_vid_get_hw_resources(
 static int _sde_encoder_phys_vid_wait_for_vblank(
 		struct sde_encoder_phys *phys_enc, bool notify)
 {
-	struct sde_encoder_wait_info wait_info;
+	struct sde_encoder_wait_info wait_info = {0};
 	int ret = 0;
 	u32 event = SDE_ENCODER_FRAME_EVENT_ERROR |
 		SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE |

+ 1 - 1
msm/sde/sde_encoder_phys_wb.c

@@ -1218,7 +1218,7 @@ static int _sde_encoder_phys_wb_wait_for_commit_done(
 	u32 event = 0;
 	u64 wb_time = 0;
 	int rc = 0;
-	struct sde_encoder_wait_info wait_info;
+	struct sde_encoder_wait_info wait_info = {0};
 
 	/* Return EWOULDBLOCK since we know the wait isn't necessary */
 	if (phys_enc->enable_state == SDE_ENC_DISABLED) {