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:
@@ -663,28 +663,23 @@ static bool _sde_encoder_phys_cmd_is_ongoing_pptx(
|
|||||||
return false;
|
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 *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;
|
bool wr_ptr_wait_success = true;
|
||||||
unsigned long lock_flags;
|
unsigned long lock_flags;
|
||||||
|
bool ret = false;
|
||||||
if (!phys_enc) {
|
struct sde_encoder_phys_cmd *cmd_enc =
|
||||||
SDE_ERROR("invalid encoder\n");
|
to_sde_encoder_phys_cmd(phys_enc);
|
||||||
return -EINVAL;
|
struct sde_hw_ctl *ctl = phys_enc->hw_ctl;
|
||||||
}
|
|
||||||
|
|
||||||
ctl = phys_enc->hw_ctl;
|
|
||||||
|
|
||||||
if (sde_encoder_phys_cmd_is_master(phys_enc))
|
if (sde_encoder_phys_cmd_is_master(phys_enc))
|
||||||
wr_ptr_wait_success = cmd_enc->wr_ptr_wait_success;
|
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 &&
|
if (wr_ptr_wait_success &&
|
||||||
(phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_POSTED_START) &&
|
(phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_POSTED_START) &&
|
||||||
ctl->ops.get_scheduler_status &&
|
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_DONE |
|
||||||
SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE);
|
SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE);
|
||||||
spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags);
|
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)
|
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))
|
if (_sde_encoder_phys_is_ppsplit_slave(phys_enc))
|
||||||
return 0;
|
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,
|
ret = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_PINGPONG,
|
||||||
&wait_info);
|
&wait_info);
|
||||||
if (ret == -ETIMEDOUT) {
|
if (ret == -ETIMEDOUT) {
|
||||||
|
if (_sde_encoder_phys_cmd_is_scheduler_idle(phys_enc))
|
||||||
|
return 0;
|
||||||
|
|
||||||
_sde_encoder_phys_cmd_handle_ppdone_timeout(phys_enc,
|
_sde_encoder_phys_cmd_handle_ppdone_timeout(phys_enc,
|
||||||
recovery_events);
|
recovery_events);
|
||||||
} else if (!ret) {
|
} else if (!ret) {
|
||||||
|
Reference in New Issue
Block a user