From 6da6eb67746085349ca0334c6732f0e5e601bba0 Mon Sep 17 00:00:00 2001 From: Veera Sundaram Sankaran Date: Fri, 14 Jun 2019 14:08:25 -0700 Subject: [PATCH] disp: msm: sde: reset ctl during wr_ptr_irq timeout wr_ptr_irq timeout signifies that the MDP is stuck on either the current or previous frame. Handle ctl reset and fence signalling as part of this timeout handling. This logic would help to recover the HW faster in case of posted-start. Change-Id: I09b3d21772df431f9fc4a58b2fd9b4fcac4a7de7 Signed-off-by: Veera Sundaram Sankaran --- msm/sde/sde_encoder.c | 23 ++++------------------- msm/sde/sde_encoder_phys.h | 6 ++++++ msm/sde/sde_encoder_phys_cmd.c | 32 ++++++++++++++++++++++---------- 3 files changed, 32 insertions(+), 29 deletions(-) diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index e2e7c6e39285..cf57639ba5ac 100644 --- a/msm/sde/sde_encoder.c +++ b/msm/sde/sde_encoder.c @@ -4611,21 +4611,11 @@ static void _sde_encoder_helper_hdr_plus_mempool_update( } } -static void _sde_encoder_needs_hw_reset(struct drm_encoder *drm_enc, - int ln_cnt1) +void sde_encoder_helper_needs_hw_reset(struct drm_encoder *drm_enc) { struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc); struct sde_encoder_phys *phys; - int ln_cnt2, i; - - /* query line count before cur_master is updated */ - if (sde_enc->cur_master && sde_enc->cur_master->ops.get_wr_line_count) - ln_cnt2 = sde_enc->cur_master->ops.get_wr_line_count( - sde_enc->cur_master); - else - ln_cnt2 = -EINVAL; - - SDE_EVT32(DRMID(drm_enc), ln_cnt1, ln_cnt2); + int i; for (i = 0; i < sde_enc->num_phys_encs; i++) { phys = sde_enc->phys_encs[i]; @@ -4643,7 +4633,7 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, struct sde_crtc *sde_crtc; struct msm_drm_private *priv = NULL; bool needs_hw_reset = false, is_cmd_mode; - int ln_cnt1 = -EINVAL, i, rc, ret = 0; + int i, rc, ret = 0; struct msm_display_info *disp_info; if (!drm_enc || !params || !drm_enc->dev || @@ -4660,11 +4650,6 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, SDE_DEBUG_ENC(sde_enc, "\n"); SDE_EVT32(DRMID(drm_enc)); - /* save this for later, in case of errors */ - if (sde_enc->cur_master && sde_enc->cur_master->ops.get_wr_line_count) - ln_cnt1 = sde_enc->cur_master->ops.get_wr_line_count( - sde_enc->cur_master); - /* update the qsync parameters for the current frame */ if (sde_enc->cur_master) sde_connector_set_qsync_params( @@ -4715,7 +4700,7 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, /* if any phys needs reset, reset all phys, in-order */ if (needs_hw_reset) - _sde_encoder_needs_hw_reset(drm_enc, ln_cnt1); + sde_encoder_helper_needs_hw_reset(drm_enc); _sde_encoder_update_master(drm_enc, params); diff --git a/msm/sde/sde_encoder_phys.h b/msm/sde/sde_encoder_phys.h index a670e4ab51c8..bf58e27893e5 100644 --- a/msm/sde/sde_encoder_phys.h +++ b/msm/sde/sde_encoder_phys.h @@ -510,6 +510,12 @@ void sde_encoder_phys_setup_cdm(struct sde_encoder_phys *phys_enc, void sde_encoder_helper_get_pp_line_count(struct drm_encoder *drm_enc, struct sde_hw_pp_vsync_info *info); +/** + * sde_encoder_helper_needs_hw_reset - hw reset helper function + * @drm_enc: Pointer to drm encoder structure + */ +void sde_encoder_helper_needs_hw_reset(struct drm_encoder *drm_enc); + /** * sde_encoder_helper_trigger_flush - control flush helper function * This helper function may be optionally specified by physical diff --git a/msm/sde/sde_encoder_phys_cmd.c b/msm/sde/sde_encoder_phys_cmd.c index ff08d721191f..e8accfd627fe 100644 --- a/msm/sde/sde_encoder_phys_cmd.c +++ b/msm/sde/sde_encoder_phys_cmd.c @@ -1415,8 +1415,11 @@ static int sde_encoder_phys_cmd_wait_for_commit_done( cmd_enc = to_sde_encoder_phys_cmd(phys_enc); /* only required for master controller */ - if (sde_encoder_phys_cmd_is_master(phys_enc)) + if (sde_encoder_phys_cmd_is_master(phys_enc)) { rc = _sde_encoder_phys_cmd_wait_for_wr_ptr(phys_enc); + if (rc == -ETIMEDOUT) + goto wait_for_idle; + } if (!rc && sde_encoder_phys_cmd_is_master(phys_enc) && cmd_enc->autorefresh.cfg.enable) @@ -1424,15 +1427,24 @@ static int sde_encoder_phys_cmd_wait_for_commit_done( /* wait for posted start or serialize trigger */ if ((atomic_read(&phys_enc->pending_kickoff_cnt) > 1) || - (!rc && phys_enc->frame_trigger_mode == - FRAME_DONE_WAIT_SERIALIZE)) { - rc = _sde_encoder_phys_cmd_wait_for_idle(phys_enc); - if (rc) { - atomic_set(&phys_enc->pending_kickoff_cnt, 0); - SDE_EVT32(DRMID(phys_enc->parent), - phys_enc->hw_pp->idx - PINGPONG_0); - SDE_ERROR("failed wait_for_idle: %d\n", rc); - } + (!rc && phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_SERIALIZE)) + goto wait_for_idle; + + return rc; + +wait_for_idle: + rc = _sde_encoder_phys_cmd_wait_for_idle(phys_enc); + if (rc) { + SDE_EVT32(DRMID(phys_enc->parent), + phys_enc->hw_pp->idx - PINGPONG_0, + phys_enc->frame_trigger_mode, + atomic_read(&phys_enc->pending_kickoff_cnt), + phys_enc->enable_state, rc); + atomic_set(&phys_enc->pending_kickoff_cnt, 0); + SDE_ERROR("pp:%d failed wait_for_idle: %d\n", + phys_enc->hw_pp->idx - PINGPONG_0, rc); + if (phys_enc->enable_state == SDE_ENC_ERR_NEEDS_HW_RESET) + sde_encoder_helper_needs_hw_reset(phys_enc->parent); } return rc;