disp: msm: sde: reset ctl on autorefresh disable failure
Reset MDP ctl path and DSI ctl on autorefresh disable failure. This will enable the hardware to recover from the hang. Change-Id: Ia9acc8573c22e0713179ef4f6ef604caacabfadb Signed-off-by: Veera Sundaram Sankaran <veeras@codeaurora.org>
This commit is contained in:

committed by
Gerrit - the friendly Code Review server

parent
363aadd666
commit
bceea4e1fe
@@ -3527,7 +3527,7 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc,
|
||||
struct msm_drm_private *priv;
|
||||
struct sde_kms *sde_kms;
|
||||
struct sde_crtc_state *cstate;
|
||||
bool is_error = false, reset_req;
|
||||
bool is_error = false;
|
||||
unsigned long flags;
|
||||
enum sde_crtc_idle_pc_state idle_pc_state;
|
||||
struct sde_encoder_kickoff_params params = { 0 };
|
||||
@@ -3539,7 +3539,6 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc,
|
||||
dev = crtc->dev;
|
||||
sde_crtc = to_sde_crtc(crtc);
|
||||
sde_kms = _sde_crtc_get_kms(crtc);
|
||||
reset_req = false;
|
||||
|
||||
if (!sde_kms || !sde_kms->dev || !sde_kms->dev->dev_private) {
|
||||
SDE_ERROR("invalid argument\n");
|
||||
@@ -3572,7 +3571,7 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc,
|
||||
params.affected_displays = _sde_crtc_get_displays_affected(crtc,
|
||||
crtc->state);
|
||||
if (sde_encoder_prepare_for_kickoff(encoder, ¶ms))
|
||||
reset_req = true;
|
||||
sde_crtc->needs_hw_reset = true;
|
||||
|
||||
if (idle_pc_state != IDLE_PC_NONE)
|
||||
sde_encoder_control_idle_pc(encoder,
|
||||
@@ -3583,13 +3582,14 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc,
|
||||
* Optionally attempt h/w recovery if any errors were detected while
|
||||
* preparing for the kickoff
|
||||
*/
|
||||
if (reset_req) {
|
||||
if (sde_crtc->needs_hw_reset) {
|
||||
sde_crtc->frame_trigger_mode = params.frame_trigger_mode;
|
||||
if (sde_crtc->frame_trigger_mode
|
||||
!= FRAME_DONE_WAIT_POSTED_START &&
|
||||
sde_crtc_reset_hw(crtc, old_state,
|
||||
params.recovery_events_enabled))
|
||||
is_error = true;
|
||||
sde_crtc->needs_hw_reset = false;
|
||||
}
|
||||
|
||||
sde_crtc_calc_fps(sde_crtc);
|
||||
|
@@ -252,6 +252,7 @@ struct sde_crtc_misr_info {
|
||||
* @ltm_hist_en : flag to indicate whether LTM hist is enabled or not
|
||||
* @ltm_buffer_lock : muttx to protect ltm_buffers allcation and free
|
||||
* @ltm_lock : Spinlock to protect ltm buffer_cnt, hist_en and ltm lists
|
||||
* @needs_hw_reset : Initiate a hw ctl reset
|
||||
*/
|
||||
struct sde_crtc {
|
||||
struct drm_crtc base;
|
||||
@@ -330,6 +331,7 @@ struct sde_crtc {
|
||||
struct drm_msm_ltm_cfg_param ltm_cfg;
|
||||
struct mutex ltm_buffer_lock;
|
||||
spinlock_t ltm_lock;
|
||||
bool needs_hw_reset;
|
||||
};
|
||||
|
||||
#define to_sde_crtc(x) container_of(x, struct sde_crtc, base)
|
||||
@@ -494,6 +496,22 @@ static inline int sde_crtc_frame_pending(struct drm_crtc *crtc)
|
||||
return atomic_read(&sde_crtc->frame_pending);
|
||||
}
|
||||
|
||||
/**
|
||||
* sde_crtc_set_needs_hw_reset - set hw reset flag, to handle reset during
|
||||
* commit kickoff
|
||||
* @crtc: Pointer to DRM crtc instance
|
||||
*/
|
||||
static inline void sde_crtc_set_needs_hw_reset(struct drm_crtc *crtc)
|
||||
{
|
||||
struct sde_crtc *sde_crtc;
|
||||
|
||||
if (!crtc)
|
||||
return;
|
||||
|
||||
sde_crtc = to_sde_crtc(crtc);
|
||||
sde_crtc->needs_hw_reset = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* sde_crtc_reset_hw - attempt hardware reset on errors
|
||||
* @crtc: Pointer to DRM crtc instance
|
||||
|
@@ -3891,7 +3891,7 @@ static void _sde_encoder_helper_hdr_plus_mempool_update(
|
||||
}
|
||||
}
|
||||
|
||||
void sde_encoder_helper_needs_hw_reset(struct drm_encoder *drm_enc)
|
||||
void sde_encoder_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;
|
||||
@@ -3975,7 +3975,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_helper_needs_hw_reset(drm_enc);
|
||||
sde_encoder_needs_hw_reset(drm_enc);
|
||||
|
||||
_sde_encoder_update_master(drm_enc, params);
|
||||
|
||||
@@ -4177,16 +4177,16 @@ int sde_encoder_helper_reset_mixers(struct sde_encoder_phys *phys_enc,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sde_encoder_prepare_commit(struct drm_encoder *drm_enc)
|
||||
int sde_encoder_prepare_commit(struct drm_encoder *drm_enc)
|
||||
{
|
||||
struct sde_encoder_virt *sde_enc;
|
||||
struct sde_encoder_phys *phys;
|
||||
int i, rc = 0;
|
||||
int i, rc = 0, ret = 0;
|
||||
struct sde_hw_ctl *ctl;
|
||||
|
||||
if (!drm_enc) {
|
||||
SDE_ERROR("invalid encoder\n");
|
||||
return;
|
||||
return -EINVAL;
|
||||
}
|
||||
sde_enc = to_sde_encoder_virt(drm_enc);
|
||||
|
||||
@@ -4200,6 +4200,9 @@ void sde_encoder_prepare_commit(struct drm_encoder *drm_enc)
|
||||
if (phys && phys->ops.prepare_commit)
|
||||
phys->ops.prepare_commit(phys);
|
||||
|
||||
if (phys->enable_state == SDE_ENC_ERR_NEEDS_HW_RESET)
|
||||
ret = -ETIMEDOUT;
|
||||
|
||||
if (phys && phys->hw_ctl) {
|
||||
ctl = phys->hw_ctl;
|
||||
/*
|
||||
@@ -4222,6 +4225,8 @@ void sde_encoder_prepare_commit(struct drm_encoder *drm_enc)
|
||||
sde_enc->cur_master->connector->base.id,
|
||||
rc);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void sde_encoder_helper_setup_misr(struct sde_encoder_phys *phys_enc,
|
||||
|
@@ -430,7 +430,7 @@ void sde_encoder_destroy(struct drm_encoder *drm_enc);
|
||||
* atomic commit, before any registers are written
|
||||
* @drm_enc: Pointer to previously created drm encoder structure
|
||||
*/
|
||||
void sde_encoder_prepare_commit(struct drm_encoder *drm_enc);
|
||||
int sde_encoder_prepare_commit(struct drm_encoder *drm_enc);
|
||||
|
||||
/**
|
||||
* sde_encoder_update_caps_for_cont_splash - update encoder settings during
|
||||
@@ -514,6 +514,12 @@ void sde_encoder_control_idle_pc(struct drm_encoder *enc, bool enable);
|
||||
*/
|
||||
int sde_encoder_in_cont_splash(struct drm_encoder *enc);
|
||||
|
||||
/**
|
||||
* sde_encoder_helper_hw_reset - hw reset helper function
|
||||
* @drm_enc: Pointer to drm encoder structure
|
||||
*/
|
||||
void sde_encoder_needs_hw_reset(struct drm_encoder *enc);
|
||||
|
||||
/**
|
||||
* sde_encoder_uidle_enable - control enable/disable of uidle
|
||||
* @drm_enc: Pointer to drm encoder structure
|
||||
|
@@ -535,12 +535,6 @@ 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
|
||||
|
@@ -1625,7 +1625,7 @@ wait_for_idle:
|
||||
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);
|
||||
sde_encoder_needs_hw_reset(phys_enc->parent);
|
||||
}
|
||||
|
||||
return rc;
|
||||
@@ -1729,6 +1729,8 @@ static void sde_encoder_phys_cmd_prepare_commit(
|
||||
> (KICKOFF_TIMEOUT_MS * USEC_PER_MSEC)) {
|
||||
SDE_ERROR_CMDENC(cmd_enc,
|
||||
"disable autorefresh failed\n");
|
||||
|
||||
phys_enc->enable_state = SDE_ENC_ERR_NEEDS_HW_RESET;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@@ -885,7 +885,12 @@ static void sde_kms_prepare_commit(struct msm_kms *kms,
|
||||
if (encoder->crtc != crtc)
|
||||
continue;
|
||||
|
||||
sde_encoder_prepare_commit(encoder);
|
||||
if (sde_encoder_prepare_commit(encoder) == -ETIMEDOUT) {
|
||||
SDE_ERROR("crtc:%d, initiating hw reset\n",
|
||||
DRMID(crtc));
|
||||
sde_encoder_needs_hw_reset(encoder);
|
||||
sde_crtc_set_needs_hw_reset(crtc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user