disp: msm: sde: fix handling the missing pp-done interrupt cases

With posted-start, ctl scheduler status and pending-kickoff
count are checked to address the missing pp-done interrupt
cases, which can occur if the IRQs are disabled for a long
time by some entity. Currently this check is done after
the wr-ptr-irq. At this point the scheduler status may
or may not be idle, based on the frame-transfer. Move this
handling after the timeout, so the scheduler is guaranteed
to be in idle state for working use-case.

Change-Id: I3fa9ecce8139ff667c1882e286571169c543c797
Signed-off-by: Veera Sundaram Sankaran <veeras@codeaurora.org>
This commit is contained in:
Veera Sundaram Sankaran 2019-10-10 17:22:07 -07:00
parent 1643b63bd7
commit e167ae786c

View File

@ -663,28 +663,23 @@ static bool _sde_encoder_phys_cmd_is_ongoing_pptx(
return false;
}
static int _sde_encoder_phys_cmd_wait_for_idle(
static bool _sde_encoder_phys_cmd_is_scheduler_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;
struct sde_hw_ctl *ctl;
bool wr_ptr_wait_success = true;
unsigned long lock_flags;
if (!phys_enc) {
SDE_ERROR("invalid encoder\n");
return -EINVAL;
}
ctl = phys_enc->hw_ctl;
bool ret = false;
struct sde_encoder_phys_cmd *cmd_enc =
to_sde_encoder_phys_cmd(phys_enc);
struct sde_hw_ctl *ctl = phys_enc->hw_ctl;
if (sde_encoder_phys_cmd_is_master(phys_enc))
wr_ptr_wait_success = cmd_enc->wr_ptr_wait_success;
/*
* Handle cases where a pp-done interrupt is missed
* due to irq latency with POSTED start
*/
if (wr_ptr_wait_success &&
(phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_POSTED_START) &&
ctl->ops.get_scheduler_status &&
@ -698,7 +693,30 @@ static int _sde_encoder_phys_cmd_wait_for_idle(
SDE_ENCODER_FRAME_EVENT_DONE |
SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE);
spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags);
return 0;
SDE_EVT32(DRMID(phys_enc->parent),
phys_enc->hw_pp->idx - PINGPONG_0,
phys_enc->hw_intf->idx - INTF_0,
atomic_read(&phys_enc->pending_kickoff_cnt));
ret = true;
}
return ret;
}
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) {
SDE_ERROR("invalid encoder\n");
return -EINVAL;
}
if (atomic_read(&phys_enc->pending_kickoff_cnt) > 1)
@ -714,9 +732,15 @@ static int _sde_encoder_phys_cmd_wait_for_idle(
if (_sde_encoder_phys_is_ppsplit_slave(phys_enc))
return 0;
if (_sde_encoder_phys_cmd_is_scheduler_idle(phys_enc))
return 0;
ret = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_PINGPONG,
&wait_info);
if (ret == -ETIMEDOUT) {
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) {