summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Salido-Moreno <adrianm@codeaurora.org>2013-05-01 19:32:23 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 20:16:51 -0700
commit39c5475a022e3d2cd5bfe27c979654d2d00aa213 (patch)
treea7defcd3693e464b9a415d9dea9a0af7a7fdb17d
parentdc237a2296f54af1f94b140e1f0c4c63467cc95c (diff)
msm: mdss: cleanup multiple vsync handlers logic
Simplify multiple vsync handlers logic by removing ref counters on handler structure and manage the same with the ref counter for irq enable/disable. At the same time ensure that the vsync lock is not being held while calling vsync enable/disable to avoid potential deadlock. Change-Id: Id79c67f21a5b2d224b2e6b1d3e0b6aa553c44945 CRs-Fixed: 482320 Signed-off-by: Adrian Salido-Moreno <adrianm@codeaurora.org>
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.h2
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_intf_video.c51
2 files changed, 20 insertions, 33 deletions
diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h
index 249f89bbaf84..e18722ca5fde 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.h
+++ b/drivers/video/fbdev/msm/mdss_mdp.h
@@ -110,8 +110,8 @@ struct mdss_mdp_ctl;
typedef void (*mdp_vsync_handler_t)(struct mdss_mdp_ctl *, ktime_t);
struct mdss_mdp_vsync_handler {
+ bool enabled;
mdp_vsync_handler_t vsync_handler;
- u32 ref_cnt;
struct list_head list;
};
diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c
index 638c73ffab92..72cbed95ee66 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c
@@ -203,13 +203,13 @@ static int mdss_mdp_video_timegen_setup(struct mdss_mdp_video_ctx *ctx,
}
-static inline void video_vsync_irq_enable(struct mdss_mdp_ctl *ctl)
+static inline void video_vsync_irq_enable(struct mdss_mdp_ctl *ctl, bool clear)
{
struct mdss_mdp_video_ctx *ctx = ctl->priv_data;
if (atomic_inc_return(&ctx->vsync_ref) == 1)
mdss_mdp_irq_enable(MDSS_MDP_IRQ_INTF_VSYNC, ctl->intf_num);
- else
+ else if (clear)
mdss_mdp_irq_clear(ctl->mdata, MDSS_MDP_IRQ_INTF_VSYNC,
ctl->intf_num);
}
@@ -227,9 +227,8 @@ static int mdss_mdp_video_add_vsync_handler(struct mdss_mdp_ctl *ctl,
{
struct mdss_mdp_video_ctx *ctx;
unsigned long flags;
- struct mdss_mdp_vsync_handler *tmp;
- bool exist = false;
int ret = 0;
+ bool irq_en = false;
if (!handle || !(handle->vsync_handler)) {
ret = -EINVAL;
@@ -244,32 +243,24 @@ static int mdss_mdp_video_add_vsync_handler(struct mdss_mdp_ctl *ctl,
}
spin_lock_irqsave(&ctx->vsync_lock, flags);
- list_for_each_entry(tmp, &(ctx->vsync_handlers), list) {
- if (tmp->vsync_handler == handle->vsync_handler) {
- exist = true;
- tmp->ref_cnt++;
- }
- }
- if (!exist) {
- handle->ref_cnt = 1;
+ if (!handle->enabled) {
+ handle->enabled = true;
list_add(&handle->list, &ctx->vsync_handlers);
+ irq_en = true;
}
-
- video_vsync_irq_enable(ctl);
spin_unlock_irqrestore(&ctx->vsync_lock, flags);
+ if (irq_en)
+ video_vsync_irq_enable(ctl, false);
exit:
return ret;
}
-/* passing NULL as handle or vsync_handler will clear all handlers */
static int mdss_mdp_video_remove_vsync_handler(struct mdss_mdp_ctl *ctl,
struct mdss_mdp_vsync_handler *handle)
{
struct mdss_mdp_video_ctx *ctx;
unsigned long flags;
- struct mdss_mdp_vsync_handler *tmp, *q;
- bool exist = true;
- bool used = false;
+ bool irq_dis = false;
ctx = (struct mdss_mdp_video_ctx *) ctl->priv_data;
if (!ctx) {
@@ -278,26 +269,21 @@ static int mdss_mdp_video_remove_vsync_handler(struct mdss_mdp_ctl *ctl,
}
spin_lock_irqsave(&ctx->vsync_lock, flags);
- list_for_each_entry_safe(tmp, q, &ctx->vsync_handlers, list) {
- if (handle && handle->vsync_handler)
- exist = (tmp->vsync_handler == handle->vsync_handler);
- if (exist) {
- tmp->ref_cnt--;
- if (handle && handle->vsync_handler)
- used = (tmp->ref_cnt != 0);
- if (!used) {
- video_vsync_irq_disable(ctl);
- list_del_init(&tmp->list);
- }
- }
+ if (handle->enabled) {
+ handle->enabled = false;
+ list_del_init(&handle->list);
+ irq_dis = true;
}
spin_unlock_irqrestore(&ctx->vsync_lock, flags);
+ if (irq_dis)
+ video_vsync_irq_disable(ctl);
return 0;
}
static int mdss_mdp_video_stop(struct mdss_mdp_ctl *ctl)
{
struct mdss_mdp_video_ctx *ctx;
+ struct mdss_mdp_vsync_handler *tmp, *handle;
int rc;
pr_debug("stop ctl=%d\n", ctl->num);
@@ -328,7 +314,8 @@ static int mdss_mdp_video_stop(struct mdss_mdp_ctl *ctl)
ctl->intf_num);
}
- mdss_mdp_video_remove_vsync_handler(ctl, NULL);
+ list_for_each_entry_safe(handle, tmp, &ctx->vsync_handlers, list)
+ mdss_mdp_video_remove_vsync_handler(ctl, handle);
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_VSYNC, ctl->intf_num,
NULL, NULL);
@@ -470,7 +457,7 @@ static int mdss_mdp_video_display(struct mdss_mdp_ctl *ctl, void *arg)
if (!ctx->wait_pending) {
ctx->wait_pending++;
- video_vsync_irq_enable(ctl);
+ video_vsync_irq_enable(ctl, true);
INIT_COMPLETION(ctx->vsync_comp);
} else {
WARN(1, "commit without wait! ctl=%d", ctl->num);