diff options
| author | Huaibin Yang <huaibiny@codeaurora.org> | 2013-07-10 14:24:51 -0700 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 20:19:04 -0700 |
| commit | d37e2a692a2403041a9a1e6cf8a4154740c8a6ae (patch) | |
| tree | 4125d18f0841834e33b9f3ac0800e6a0225bdc20 | |
| parent | 8ca4f10d299b21ff3d1ecc5116ab1a1faaae4321 (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.c | 16 |
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; |
