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 <veeras@codeaurora.org>
This commit is contained in:
Veera Sundaram Sankaran 2019-06-14 14:08:25 -07:00
parent a8974603d1
commit 6da6eb6774
3 changed files with 32 additions and 29 deletions

View File

@ -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);

View File

@ -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

View File

@ -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;