From d26bf3c6fdcd20f439f6f3a7a65071c8033531f0 Mon Sep 17 00:00:00 2001 From: Steve Cohen Date: Wed, 22 Apr 2020 00:00:30 -0400 Subject: [PATCH] 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 --- msm/sde/sde_encoder_phys.h | 2 ++ msm/sde/sde_encoder_phys_cmd.c | 42 +++++++++++++++++++--------------- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/msm/sde/sde_encoder_phys.h b/msm/sde/sde_encoder_phys.h index 4960907949c4..8e870b6c044e 100644 --- a/msm/sde/sde_encoder_phys.h +++ b/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) diff --git a/msm/sde/sde_encoder_phys_cmd.c b/msm/sde/sde_encoder_phys_cmd.c index 2304665003f5..5ab43c879238 100644 --- a/msm/sde/sde_encoder_phys_cmd.c +++ b/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,