From 6f06e5cd6fa598232d4ce16733f98fc4750ab944 Mon Sep 17 00:00:00 2001 From: Dhaval Patel Date: Tue, 20 Aug 2019 15:44:32 -0700 Subject: [PATCH] disp: msm: sde: wait for specific pp_done instead of zero 2 Frames transfer pending is possible with posted start. One ongoing frame and another triggered frame. Current SW waits for pp_done interrupt if pending frame count is greater than 1. It is possible that interrupt may be missed for ongoing frame. In that case, SW should run pp_done wait for one by one frame instead of two frames together. It allows encoder to check the ctl scheduler status and trigger the frame done event on time. Change-Id: I4817842292d96747890ee70da8a5bdf9b56816ed Signed-off-by: Dhaval Patel --- msm/sde/sde_encoder.c | 9 ++++++--- msm/sde/sde_encoder_phys.h | 2 ++ msm/sde/sde_encoder_phys_cmd.c | 19 ++++++++++++++----- msm/sde/sde_encoder_phys_vid.c | 2 +- msm/sde/sde_encoder_phys_wb.c | 2 +- 5 files changed, 24 insertions(+), 10 deletions(-) diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index 6643600468..0748bfd43b 100644 --- a/msm/sde/sde_encoder.c +++ b/msm/sde/sde_encoder.c @@ -408,13 +408,16 @@ static int _sde_encoder_wait_timeout(int32_t drm_id, int32_t hw_id, do { rc = wait_event_timeout(*(info->wq), - atomic_read(info->atomic_cnt) == 0, wait_time_jiffies); + atomic_read(info->atomic_cnt) == info->count_check, + wait_time_jiffies); cur_ktime = ktime_get(); SDE_EVT32(drm_id, hw_id, rc, ktime_to_ms(cur_ktime), - timeout_ms, atomic_read(info->atomic_cnt)); + timeout_ms, atomic_read(info->atomic_cnt), + info->count_check); /* If we timed out, counter is valid and time is less, wait again */ - } while (atomic_read(info->atomic_cnt) && (rc == 0) && + } while ((atomic_read(info->atomic_cnt) != info->count_check) && + (rc == 0) && (ktime_compare_safe(exp_ktime, cur_ktime) > 0)); return rc; diff --git a/msm/sde/sde_encoder_phys.h b/msm/sde/sde_encoder_phys.h index 83232d7464..db85d0d7c8 100644 --- a/msm/sde/sde_encoder_phys.h +++ b/msm/sde/sde_encoder_phys.h @@ -458,11 +458,13 @@ struct sde_enc_phys_init_params { * sde_encoder_wait_info - container for passing arguments to irq wait functions * @wq: wait queue structure * @atomic_cnt: wait until atomic_cnt equals zero + * @count_check: wait for specific atomic_cnt instead of zero. * @timeout_ms: timeout value in milliseconds */ struct sde_encoder_wait_info { wait_queue_head_t *wq; atomic_t *atomic_cnt; + u32 count_check; s64 timeout_ms; }; diff --git a/msm/sde/sde_encoder_phys_cmd.c b/msm/sde/sde_encoder_phys_cmd.c index 8034784f6f..c2becbef81 100644 --- a/msm/sde/sde_encoder_phys_cmd.c +++ b/msm/sde/sde_encoder_phys_cmd.c @@ -647,10 +647,11 @@ static int _sde_encoder_phys_cmd_wait_for_idle( { struct sde_encoder_phys_cmd *cmd_enc = to_sde_encoder_phys_cmd(phys_enc); - struct sde_encoder_wait_info wait_info; + struct sde_encoder_wait_info wait_info = {0}; bool recovery_events; int ret; struct sde_hw_ctl *ctl; + bool wr_ptr_wait_success = true; if (!phys_enc) { SDE_ERROR("invalid encoder\n"); @@ -658,7 +659,11 @@ static int _sde_encoder_phys_cmd_wait_for_idle( } ctl = phys_enc->hw_ctl; - if (cmd_enc->wr_ptr_wait_success && + + if (sde_encoder_phys_cmd_is_master(phys_enc)) + wr_ptr_wait_success = cmd_enc->wr_ptr_wait_success; + + if (wr_ptr_wait_success && (phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_POSTED_START) && ctl->ops.get_scheduler_status && (ctl->ops.get_scheduler_status(ctl) & BIT(0)) && @@ -672,6 +677,9 @@ static int _sde_encoder_phys_cmd_wait_for_idle( return 0; } + if (atomic_read(&phys_enc->pending_kickoff_cnt) > 1) + wait_info.count_check = 1; + wait_info.wq = &phys_enc->pending_kickoff_wq; wait_info.atomic_cnt = &phys_enc->pending_kickoff_cnt; wait_info.timeout_ms = KICKOFF_TIMEOUT_MS; @@ -707,7 +715,7 @@ static int _sde_encoder_phys_cmd_wait_for_autorefresh_done( { struct sde_encoder_phys_cmd *cmd_enc = to_sde_encoder_phys_cmd(phys_enc); - struct sde_encoder_wait_info wait_info; + struct sde_encoder_wait_info wait_info = {0}; int ret = 0; if (!phys_enc) { @@ -1334,7 +1342,7 @@ static int _sde_encoder_phys_cmd_wait_for_wr_ptr( { struct sde_encoder_phys_cmd *cmd_enc = to_sde_encoder_phys_cmd(phys_enc); - struct sde_encoder_wait_info wait_info; + struct sde_encoder_wait_info wait_info = {0}; int ret; bool frame_pending = true; struct sde_hw_ctl *ctl; @@ -1383,6 +1391,7 @@ static int _sde_encoder_phys_cmd_wait_for_wr_ptr( } cmd_enc->wr_ptr_wait_success = (ret == 0) ? true : false; + return ret; } @@ -1461,7 +1470,7 @@ static int sde_encoder_phys_cmd_wait_for_vblank( { int rc = 0; struct sde_encoder_phys_cmd *cmd_enc; - struct sde_encoder_wait_info wait_info; + struct sde_encoder_wait_info wait_info = {0}; if (!phys_enc) return -EINVAL; diff --git a/msm/sde/sde_encoder_phys_vid.c b/msm/sde/sde_encoder_phys_vid.c index b49fea311e..f290c0e1e9 100644 --- a/msm/sde/sde_encoder_phys_vid.c +++ b/msm/sde/sde_encoder_phys_vid.c @@ -864,7 +864,7 @@ static void sde_encoder_phys_vid_get_hw_resources( static int _sde_encoder_phys_vid_wait_for_vblank( struct sde_encoder_phys *phys_enc, bool notify) { - struct sde_encoder_wait_info wait_info; + struct sde_encoder_wait_info wait_info = {0}; int ret = 0; u32 event = SDE_ENCODER_FRAME_EVENT_ERROR | SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE | diff --git a/msm/sde/sde_encoder_phys_wb.c b/msm/sde/sde_encoder_phys_wb.c index ba9418c0a0..0d715c78f9 100644 --- a/msm/sde/sde_encoder_phys_wb.c +++ b/msm/sde/sde_encoder_phys_wb.c @@ -1218,7 +1218,7 @@ static int _sde_encoder_phys_wb_wait_for_commit_done( u32 event = 0; u64 wb_time = 0; int rc = 0; - struct sde_encoder_wait_info wait_info; + struct sde_encoder_wait_info wait_info = {0}; /* Return EWOULDBLOCK since we know the wait isn't necessary */ if (phys_enc->enable_state == SDE_ENC_DISABLED) {