msm: mdss: generate panic if HW recovery fails during underrun

HW recovery is triggered when underrun happens. If pipe
XIN halt status is checked during the recovery time frame, it
would fail as the hw is in the recovery process. Check for the
ctl reset status before every frame update and if it is set,
add the same polling mechanism used while sw reset is triggered
to ensure hw reset is complete before checking the pipe status.
And add panic if hw fails to recover within the max polling time.

Change-Id: Ia672195b519e76bc4560d4555222c26fde094a64
Signed-off-by: Dhaval Patel <pdhaval@codeaurora.org>
Signed-off-by: Veera Sundaram Sankaran <veeras@codeaurora.org>
This commit is contained in:
Dhaval Patel 2015-07-27 19:01:28 -07:00 committed by David Keitel
parent 7dc67b0f2a
commit d0d79bf6f7
3 changed files with 55 additions and 17 deletions

View file

@ -1209,6 +1209,7 @@ int mdss_mdp_video_reconfigure_splash_done(struct mdss_mdp_ctl *ctl,
int mdss_mdp_cmd_reconfigure_splash_done(struct mdss_mdp_ctl *ctl,
bool handoff);
int mdss_mdp_ctl_splash_finish(struct mdss_mdp_ctl *ctl, bool handoff);
void mdss_mdp_check_ctl_reset_status(struct mdss_mdp_ctl *ctl);
int mdss_mdp_ctl_setup(struct mdss_mdp_ctl *ctl);
int mdss_mdp_ctl_split_display_setup(struct mdss_mdp_ctl *ctl,
struct mdss_panel_data *pdata);

View file

@ -3841,6 +3841,54 @@ static void mdss_mdp_pipe_reset(struct mdss_mdp_mixer *mixer, bool is_recovery)
}
}
static u32 mdss_mdp_poll_ctl_reset_status(struct mdss_mdp_ctl *ctl, u32 cnt)
{
u32 status;
/*
* it takes around 30us to have mdp finish resetting its ctl path
* poll every 50us so that reset should be completed at 1st poll
*/
do {
udelay(50);
status = mdss_mdp_ctl_read(ctl, MDSS_MDP_REG_CTL_SW_RESET);
status &= 0x01;
pr_debug("status=%x, count=%d\n", status, cnt);
cnt--;
} while (cnt > 0 && status);
return status;
}
/*
* mdss_mdp_check_ctl_reset_status() - checks ctl reset status
* @ctl: mdp controller
*
* This function checks the ctl reset status before every frame update.
* If the reset bit is set, it keeps polling the status till the hw
* reset is complete. And does a panic if hw fails to complet the reset
* with in the max poll interval.
*/
void mdss_mdp_check_ctl_reset_status(struct mdss_mdp_ctl *ctl)
{
u32 status;
if (!ctl)
return;
status = mdss_mdp_ctl_read(ctl, MDSS_MDP_REG_CTL_SW_RESET);
status &= 0x01;
if (!status)
return;
pr_debug("hw ctl reset is set for ctl:%d\n", ctl->num);
status = mdss_mdp_poll_ctl_reset_status(ctl, 5);
if (status) {
pr_err("hw recovery is not complete for ctl:%d\n", ctl->num);
MDSS_XLOG_TOUT_HANDLER("mdp", "vbif", "vbif_nrt", "dbg_bus",
"vbif_dbg_bus", "panic");
}
}
/*
* mdss_mdp_ctl_reset() - reset mdp ctl path.
* @ctl: mdp controller.
@ -3851,8 +3899,7 @@ static void mdss_mdp_pipe_reset(struct mdss_mdp_mixer *mixer, bool is_recovery)
*/
int mdss_mdp_ctl_reset(struct mdss_mdp_ctl *ctl, bool is_recovery)
{
u32 status = 1;
int cnt = 20;
u32 status;
struct mdss_mdp_mixer *mixer;
if (!ctl) {
@ -3863,17 +3910,9 @@ int mdss_mdp_ctl_reset(struct mdss_mdp_ctl *ctl, bool is_recovery)
mixer = ctl->mixer_left;
mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_SW_RESET, 1);
/*
* it takes around 30us to have mdp finish resetting its ctl path
* poll every 50us so that reset should be completed at 1st poll
*/
do {
udelay(50);
status = mdss_mdp_ctl_read(ctl, MDSS_MDP_REG_CTL_SW_RESET);
status &= 0x01;
pr_debug("status=%x\n", status);
cnt--;
} while (cnt > 0 && status);
status = mdss_mdp_poll_ctl_reset_status(ctl, 20);
if (status)
pr_err("sw ctl:%d reset timedout\n", ctl->num);
if (mixer) {
mdss_mdp_pipe_reset(mixer, is_recovery);
@ -3882,10 +3921,7 @@ int mdss_mdp_ctl_reset(struct mdss_mdp_ctl *ctl, bool is_recovery)
mdss_mdp_pipe_reset(ctl->mixer_right, is_recovery);
}
if (!cnt)
pr_err("ctl%d reset timedout\n", ctl->num);
return (!cnt) ? -EAGAIN : 0;
return (status) ? -EAGAIN : 0;
}
/*

View file

@ -1953,6 +1953,7 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd,
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON);
mdss_mdp_check_ctl_reset_status(ctl);
__vsync_set_vsync_handler(mfd);
__validate_and_set_roi(mfd, data);