summaryrefslogtreecommitdiff
path: root/drivers/video/fbdev
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2016-12-01 16:39:29 -0800
committerGerrit - the friendly Code Review server <code-review@localhost>2016-12-01 16:39:28 -0800
commitd3191bd93424229e167f9cf1c58bac8f235a7d78 (patch)
tree4d754d59e64b7b57c831063d0b2de7f41735470e /drivers/video/fbdev
parentc2cbb11bf972db542cbd637ea4c4215b82aa1df5 (diff)
parent13217ef8f3116f0022087d0378bd26b7dce17fdc (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.h8
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_ctl.c15
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c3
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_overlay.c25
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, &param);
+
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;
}