summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHuaibin Yang <huaibiny@codeaurora.org>2013-07-10 14:24:51 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 20:19:04 -0700
commitd37e2a692a2403041a9a1e6cf8a4154740c8a6ae (patch)
tree4125d18f0841834e33b9f3ac0800e6a0225bdc20
parent8ca4f10d299b21ff3d1ecc5116ab1a1faaae4321 (diff)
msm: mdss: cancel or wait for the clock work to finish
The clock work has to be finished in mdp cmd stop function during adb shell stop or suspend, otherwise, system crashes due to the unreleased mutex lock in work queue. First, the stop_comp completion is issued from isr, not from work queue, so that rdptr ticks can be done without dependency on work queue, then cancel_work_sync is called to guarantee the clk work is either cancelled or finished, and finally clk off is called again to make sure clks are shut down. CRs-fixed: 511249 Change-Id: Iadca3ffce7999e31e2a720a5ad6330f939b4ea98 Signed-off-by: Huaibin Yang <huaibiny@codeaurora.org>
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c16
1 files changed, 9 insertions, 7 deletions
diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
index d0c18182458b..cb4c1f2acc8a 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
@@ -224,7 +224,6 @@ static inline void mdss_mdp_cmd_clk_off(struct mdss_mdp_cmd_ctx *ctx)
mdss_mdp_ctl_intf_event
(ctx->ctl, MDSS_EVENT_PANEL_CLK_CTRL, (void *)0);
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
- complete(&ctx->stop_comp);
}
mutex_unlock(&ctx->clk_mtx);
}
@@ -255,6 +254,7 @@ static void mdss_mdp_cmd_readptr_done(void *arg)
if (ctx->rdptr_enabled == 0) {
mdss_mdp_irq_disable_nosync
(MDSS_MDP_IRQ_PING_PONG_RD_PTR, ctx->pp_num);
+ complete(&ctx->stop_comp);
schedule_work(&ctx->clk_work);
}
@@ -456,7 +456,7 @@ int mdss_mdp_cmd_stop(struct mdss_mdp_ctl *ctl)
struct mdss_mdp_cmd_ctx *ctx;
unsigned long flags;
int need_wait = 0;
- int ret;
+ int ret = 0;
ctx = (struct mdss_mdp_cmd_ctx *) ctl->priv_data;
if (!ctx) {
@@ -474,13 +474,15 @@ int mdss_mdp_cmd_stop(struct mdss_mdp_ctl *ctl)
}
spin_unlock_irqrestore(&ctx->clk_lock, flags);
- if (need_wait) {
+ if (need_wait)
if (wait_for_completion_timeout(&ctx->stop_comp, STOP_TIMEOUT)
- <= 0) {
+ <= 0)
WARN(1, "stop cmd time out\n");
- mdss_mdp_cmd_clk_off(ctx);
- }
- }
+
+ if (cancel_work_sync(&ctx->clk_work))
+ pr_debug("no pending clk work\n");
+
+ mdss_mdp_cmd_clk_off(ctx);
ctx->panel_on = 0;