diff options
| author | Linux Build Service Account <lnxbuild@localhost> | 2016-12-01 16:39:29 -0800 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2016-12-01 16:39:28 -0800 |
| commit | d3191bd93424229e167f9cf1c58bac8f235a7d78 (patch) | |
| tree | 4d754d59e64b7b57c831063d0b2de7f41735470e /drivers/video/fbdev | |
| parent | c2cbb11bf972db542cbd637ea4c4215b82aa1df5 (diff) | |
| parent | 13217ef8f3116f0022087d0378bd26b7dce17fdc (diff) | |
Merge "msm: mdss: avoid scheduling pp work during continuous updates"
Diffstat (limited to 'drivers/video/fbdev')
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp.h | 8 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_ctl.c | 15 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c | 3 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_overlay.c | 25 |
4 files changed, 40 insertions, 11 deletions
diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h index c5cec4cd6f93..20aeabfdf9a4 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.h +++ b/drivers/video/fbdev/msm/mdss_mdp.h @@ -22,6 +22,7 @@ #include <linux/notifier.h> #include <linux/irqreturn.h> #include <linux/kref.h> +#include <linux/kthread.h> #include "mdss.h" #include "mdss_mdp_hwio.h" @@ -550,6 +551,7 @@ struct mdss_mdp_ctl { /* dynamic resolution switch during cont-splash handoff */ bool switch_with_handoff; struct mdss_mdp_avr_info avr_info; + bool commit_in_progress; }; struct mdss_mdp_mixer { @@ -931,7 +933,6 @@ struct mdss_overlay_private { struct sw_sync_timeline *vsync_timeline; struct mdss_mdp_vsync_handler vsync_retire_handler; - struct work_struct retire_work; int retire_cnt; bool kickoff_released; u32 cursor_ndx[2]; @@ -943,6 +944,11 @@ struct mdss_overlay_private { struct mdss_mdp_cwb cwb; wait_queue_head_t wb_waitq; atomic_t wb_busy; + bool allow_kickoff; + + struct kthread_worker worker; + struct kthread_work vsync_work; + struct task_struct *thread; }; struct mdss_mdp_set_ot_params { diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c index 1c013ae723aa..c80d8f47bbb7 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c +++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c @@ -5788,7 +5788,9 @@ int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg, } else { sctl_flush_bits = sctl->flush_bits; } + sctl->commit_in_progress = true; } + ctl->commit_in_progress = true; ctl_flush_bits = ctl->flush_bits; ATRACE_END("postproc_programming"); @@ -5916,11 +5918,16 @@ int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg, ATRACE_BEGIN("flush_kickoff"); mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_FLUSH, ctl_flush_bits); - if (sctl && sctl_flush_bits) { - mdss_mdp_ctl_write(sctl, MDSS_MDP_REG_CTL_FLUSH, - sctl_flush_bits); - sctl->flush_bits = 0; + if (sctl) { + if (sctl_flush_bits) { + mdss_mdp_ctl_write(sctl, MDSS_MDP_REG_CTL_FLUSH, + sctl_flush_bits); + sctl->flush_bits = 0; + } + sctl->commit_in_progress = false; } + ctl->commit_in_progress = false; + MDSS_XLOG(ctl->intf_num, ctl_flush_bits, sctl_flush_bits, split_lm_valid); wmb(); diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c index a71c7254de7c..4852fc73f040 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c +++ b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c @@ -1267,7 +1267,8 @@ static void mdss_mdp_cmd_pingpong_done(void *arg) atomic_read(&ctx->koff_cnt)); if (sync_ppdone) { atomic_inc(&ctx->pp_done_cnt); - schedule_work(&ctx->pp_done_work); + if (!ctl->commit_in_progress) + schedule_work(&ctx->pp_done_work); mdss_mdp_resource_control(ctl, MDP_RSRC_CTL_EVENT_PP_DONE); diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c index 154b9d86e67c..b0e54d22de5c 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c +++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c @@ -5580,7 +5580,7 @@ ctl_stop: * retire_signal api checks for retire_cnt with sync_mutex lock. */ - flush_work(&mdp5_data->retire_work); + flush_kthread_work(&mdp5_data->vsync_work); } mutex_lock(&mdp5_data->ov_lock); @@ -5783,13 +5783,13 @@ static void __vsync_retire_handle_vsync(struct mdss_mdp_ctl *ctl, ktime_t t) } mdp5_data = mfd_to_mdp5_data(mfd); - schedule_work(&mdp5_data->retire_work); + queue_kthread_work(&mdp5_data->worker, &mdp5_data->vsync_work); } -static void __vsync_retire_work_handler(struct work_struct *work) +static void __vsync_retire_work_handler(struct kthread_work *work) { struct mdss_overlay_private *mdp5_data = - container_of(work, typeof(*mdp5_data), retire_work); + container_of(work, typeof(*mdp5_data), vsync_work); if (!mdp5_data->ctl || !mdp5_data->ctl->mfd) return; @@ -5889,6 +5889,7 @@ static int __vsync_retire_setup(struct msm_fb_data_type *mfd) { struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd); char name[24]; + struct sched_param param = { .sched_priority = 5 }; snprintf(name, sizeof(name), "mdss_fb%d_retire", mfd->index); mdp5_data->vsync_timeline = sw_sync_timeline_create(name); @@ -5896,12 +5897,26 @@ static int __vsync_retire_setup(struct msm_fb_data_type *mfd) pr_err("cannot vsync create time line"); return -ENOMEM; } + + init_kthread_worker(&mdp5_data->worker); + init_kthread_work(&mdp5_data->vsync_work, __vsync_retire_work_handler); + + mdp5_data->thread = kthread_run(kthread_worker_fn, + &mdp5_data->worker, "vsync_retire_work"); + + if (IS_ERR(mdp5_data->thread)) { + pr_err("unable to start vsync thread\n"); + mdp5_data->thread = NULL; + return -ENOMEM; + } + + sched_setscheduler(mdp5_data->thread, SCHED_FIFO, ¶m); + mfd->mdp_sync_pt_data.get_retire_fence = __vsync_retire_get_fence; mdp5_data->vsync_retire_handler.vsync_handler = __vsync_retire_handle_vsync; mdp5_data->vsync_retire_handler.cmd_post_flush = false; - INIT_WORK(&mdp5_data->retire_work, __vsync_retire_work_handler); return 0; } |
