From e167ae786c380ff6f9911157ffd6f56e10090f80 Mon Sep 17 00:00:00 2001 From: Veera Sundaram Sankaran Date: Thu, 10 Oct 2019 17:22:07 -0700 Subject: [PATCH] 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 --- msm/sde/sde_encoder_phys_cmd.c | 54 ++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/msm/sde/sde_encoder_phys_cmd.c b/msm/sde/sde_encoder_phys_cmd.c index ba1c6ac844..66ea27738a 100644 --- a/msm/sde/sde_encoder_phys_cmd.c +++ b/msm/sde/sde_encoder_phys_cmd.c @@ -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) {