Browse Source

disp: msm: sde: move HW recovery outside ppdone wait

With posted start enabled SW no longer waits for ppdone events
unless more than one frame is in queue. HW recovery logic relied
on these waits to know when we recover from a timeout. This
change moves the HW recovery SUCCESS event signalling outside of
the wait to ensure this event is sent to user-space regardless
of the status of posted start.

Change-Id: I8896e8126284b415513499723ccf0155ee8bc6a7
Signed-off-by: Steve Cohen <[email protected]>
Steve Cohen 5 năm trước cách đây
mục cha
commit
d26bf3c6fd
2 tập tin đã thay đổi với 25 bổ sung19 xóa
  1. 2 0
      msm/sde/sde_encoder_phys.h
  2. 23 19
      msm/sde/sde_encoder_phys_cmd.c

+ 2 - 0
msm/sde/sde_encoder_phys.h

@@ -293,6 +293,7 @@ struct sde_encoder_irq {
  *				programming ROT and MDP fetch start
  * @frame_trigger_mode:		frame trigger mode indication for command
  *				mode display
+ * @recovered:			flag set to true when recovered from pp timeout
  */
 struct sde_encoder_phys {
 	struct drm_encoder *parent;
@@ -335,6 +336,7 @@ struct sde_encoder_phys {
 	bool in_clone_mode;
 	int vfp_cached;
 	enum frame_trigger_mode_type frame_trigger_mode;
+	bool recovered;
 };
 
 static inline int sde_encoder_phys_inc_pending(struct sde_encoder_phys *phys)

+ 23 - 19
msm/sde/sde_encoder_phys_cmd.c

@@ -173,11 +173,14 @@ static void _sde_encoder_phys_cmd_update_intf_cfg(
 static void sde_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx)
 {
 	struct sde_encoder_phys *phys_enc = arg;
+	struct sde_encoder_phys_cmd *cmd_enc;
 	u32 event = 0;
 
 	if (!phys_enc || !phys_enc->hw_pp)
 		return;
 
+	cmd_enc = to_sde_encoder_phys_cmd(phys_enc);
+
 	SDE_ATRACE_BEGIN("pp_done_irq");
 
 	/* notify all synchronous clients first, then asynchronous clients */
@@ -188,6 +191,8 @@ static void sde_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx)
 		spin_lock(phys_enc->enc_spinlock);
 		phys_enc->parent_ops.handle_frame_done(phys_enc->parent,
 				phys_enc, event);
+		if (cmd_enc->pp_timeout_report_cnt)
+			phys_enc->recovered = true;
 		spin_unlock(phys_enc->enc_spinlock);
 	}
 
@@ -482,11 +487,12 @@ static void sde_encoder_phys_cmd_mode_set(
 }
 
 static int _sde_encoder_phys_cmd_handle_ppdone_timeout(
-		struct sde_encoder_phys *phys_enc,
-		bool recovery_events)
+		struct sde_encoder_phys *phys_enc)
 {
 	struct sde_encoder_phys_cmd *cmd_enc =
 			to_sde_encoder_phys_cmd(phys_enc);
+	bool recovery_events = sde_encoder_recovery_events_enabled(
+			phys_enc->parent);
 	u32 frame_event = SDE_ENCODER_FRAME_EVENT_ERROR
 				| SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE;
 	struct drm_connector *conn;
@@ -728,10 +734,7 @@ static bool _sde_encoder_phys_cmd_is_scheduler_idle(
 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) {
@@ -745,8 +748,6 @@ static int _sde_encoder_phys_cmd_wait_for_idle(
 	wait_info.wq = &phys_enc->pending_kickoff_wq;
 	wait_info.atomic_cnt = &phys_enc->pending_kickoff_cnt;
 	wait_info.timeout_ms = KICKOFF_TIMEOUT_MS;
-	recovery_events = sde_encoder_recovery_events_enabled(
-			phys_enc->parent);
 
 	/* slave encoder doesn't enable for ppsplit */
 	if (_sde_encoder_phys_is_ppsplit_slave(phys_enc))
@@ -761,18 +762,7 @@ static int _sde_encoder_phys_cmd_wait_for_idle(
 		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) {
-		if (cmd_enc->pp_timeout_report_cnt && recovery_events) {
-			struct drm_connector *conn = phys_enc->connector;
-
-			sde_connector_event_notify(conn,
-					DRM_EVENT_SDE_HW_RECOVERY,
-					sizeof(uint8_t),
-					SDE_RECOVERY_SUCCESS);
-		}
-		cmd_enc->pp_timeout_report_cnt = 0;
+		_sde_encoder_phys_cmd_handle_ppdone_timeout(phys_enc);
 	}
 
 	return ret;
@@ -1379,6 +1369,7 @@ static int sde_encoder_phys_cmd_prepare_for_kickoff(
 			to_sde_encoder_phys_cmd(phys_enc);
 	int ret = 0;
 	u32 extra_frame_trigger_time;
+	bool recovery_events;
 
 	if (!phys_enc || !phys_enc->hw_pp) {
 		SDE_ERROR("invalid encoder\n");
@@ -1407,6 +1398,19 @@ static int sde_encoder_phys_cmd_prepare_for_kickoff(
 		}
 	}
 
+	if (phys_enc->recovered) {
+		recovery_events = sde_encoder_recovery_events_enabled(
+				phys_enc->parent);
+		if (cmd_enc->pp_timeout_report_cnt && recovery_events)
+			sde_connector_event_notify(phys_enc->connector,
+					DRM_EVENT_SDE_HW_RECOVERY,
+					sizeof(uint8_t),
+					SDE_RECOVERY_SUCCESS);
+
+		cmd_enc->pp_timeout_report_cnt = 0;
+		phys_enc->recovered = false;
+	}
+
 	if (sde_connector_is_qsync_updated(phys_enc->connector)) {
 		tc_cfg.sync_threshold_start =
 			_get_tearcheck_threshold(phys_enc,