diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c index d9fb4534ef647764f316915ab147393fac9afa82..957fe440e5cf539c2ac25bb77b5ab912034f2df4 100644 --- a/drivers/video/msm/mdss/mdss_fb.c +++ b/drivers/video/msm/mdss/mdss_fb.c @@ -530,7 +530,6 @@ static int mdss_fb_probe(struct platform_device *pdev) mfd->mdp = *mdp_instance; INIT_LIST_HEAD(&mfd->proc_list); - mutex_init(&mfd->lock); mutex_init(&mfd->bl_lock); fbi_list[fbi_list_index++] = fbi; diff --git a/drivers/video/msm/mdss/mdss_fb.h b/drivers/video/msm/mdss/mdss_fb.h index d3d6b654bc93b927e4cba23e96a5e6bc178ff35b..4db725d69527dc46283030d29a29ecb18a94fd72 100644 --- a/drivers/video/msm/mdss/mdss_fb.h +++ b/drivers/video/msm/mdss/mdss_fb.h @@ -200,7 +200,6 @@ struct msm_fb_data_type { u32 bl_updated; u32 bl_level_old; struct mutex bl_lock; - struct mutex lock; struct platform_device *pdev; diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h index ca44b0990ecfb3df0ab5b3488f2d65c4fdc17867..7a97593cff48462d40e0da31575a1c511f8f7d2f 100644 --- a/drivers/video/msm/mdss/mdss_mdp.h +++ b/drivers/video/msm/mdss/mdss_mdp.h @@ -409,8 +409,7 @@ struct mdss_mdp_pipe { struct mdss_mdp_data back_buf; struct mdss_mdp_data front_buf; - struct list_head used_list; - struct list_head cleanup_list; + struct list_head list; struct mdp_overlay_pp_params pp_cfg; struct mdss_pipe_pp_res pp_res; @@ -436,6 +435,8 @@ struct mdss_overlay_private { struct mutex ov_lock; struct mdss_mdp_ctl *ctl; struct mdss_mdp_wb *wb; + + struct mutex list_lock; struct list_head overlay_list; struct list_head pipes_used; struct list_head pipes_cleanup; diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c index 186437cf84c0523208e509a515a8342e1a7e322e..c4d80d5a3abf7fc0c33405fe2a38433691abbbce 100644 --- a/drivers/video/msm/mdss/mdss_mdp_overlay.c +++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c @@ -566,9 +566,9 @@ static int mdss_mdp_overlay_pipe_setup(struct msm_fb_data_type *mfd, return ret; } - mutex_lock(&mfd->lock); - list_add(&pipe->used_list, &mdp5_data->pipes_used); - mutex_unlock(&mfd->lock); + mutex_lock(&mdp5_data->list_lock); + list_add(&pipe->list, &mdp5_data->pipes_used); + mutex_unlock(&mdp5_data->list_lock); pipe->mixer_left = mixer; pipe->mfd = mfd; pipe->pid = current->tgid; @@ -808,21 +808,21 @@ static int mdss_mdp_overlay_pipe_setup(struct msm_fb_data_type *mfd, exit_fail: mdss_mdp_pipe_unmap(pipe); - mutex_lock(&mfd->lock); + mutex_lock(&mdp5_data->list_lock); if (pipe->play_cnt == 0) { pr_debug("failed for pipe %d\n", pipe->num); - if (!list_empty(&pipe->used_list)) - list_del_init(&pipe->used_list); + if (!list_empty(&pipe->list)) + list_del_init(&pipe->list); mdss_mdp_pipe_destroy(pipe); } /* invalidate any overlays in this framebuffer after failure */ - list_for_each_entry(pipe, &mdp5_data->pipes_used, used_list) { + list_for_each_entry(pipe, &mdp5_data->pipes_used, list) { pr_debug("freeing allocations for pipe %d\n", pipe->num); mdss_mdp_smp_unreserve(pipe); pipe->params_changed = 0; } - mutex_unlock(&mfd->lock); + mutex_unlock(&mdp5_data->list_lock); return ret; } @@ -954,10 +954,9 @@ static void mdss_mdp_overlay_cleanup(struct msm_fb_data_type *mfd) bool recovery_mode = false; LIST_HEAD(destroy_pipes); - mutex_lock(&mfd->lock); - list_for_each_entry_safe(pipe, tmp, &mdp5_data->pipes_cleanup, - cleanup_list) { - list_move(&pipe->cleanup_list, &destroy_pipes); + mutex_lock(&mdp5_data->list_lock); + list_for_each_entry_safe(pipe, tmp, &mdp5_data->pipes_cleanup, list) { + list_move(&pipe->list, &destroy_pipes); /* make sure pipe fetch has been halted before freeing buffer */ if (mdss_mdp_pipe_fetch_halt(pipe)) { @@ -985,7 +984,7 @@ static void mdss_mdp_overlay_cleanup(struct msm_fb_data_type *mfd) __mdss_mdp_overlay_free_list_purge(mfd); - list_for_each_entry(pipe, &mdp5_data->pipes_used, used_list) { + list_for_each_entry(pipe, &mdp5_data->pipes_used, list) { if (pipe->back_buf.num_planes) { /* make back buffer active */ __mdss_mdp_overlay_free_list_add(mfd, &pipe->front_buf); @@ -993,7 +992,7 @@ static void mdss_mdp_overlay_cleanup(struct msm_fb_data_type *mfd) } } - list_for_each_entry_safe(pipe, tmp, &destroy_pipes, cleanup_list) { + list_for_each_entry_safe(pipe, tmp, &destroy_pipes, list) { /* * in case of secure UI, the buffer needs to be released as * soon as session is closed. @@ -1003,10 +1002,10 @@ static void mdss_mdp_overlay_cleanup(struct msm_fb_data_type *mfd) else __mdss_mdp_overlay_free_list_add(mfd, &pipe->front_buf); mdss_mdp_overlay_free_buf(&pipe->back_buf); - list_del_init(&pipe->cleanup_list); + list_del_init(&pipe->list); mdss_mdp_pipe_destroy(pipe); } - mutex_unlock(&mfd->lock); + mutex_unlock(&mdp5_data->list_lock); } static void __mdss_mdp_handoff_cleanup_pipes(struct msm_fb_data_type *mfd, @@ -1039,8 +1038,7 @@ static void __mdss_mdp_handoff_cleanup_pipes(struct msm_fb_data_type *mfd, pipe = &pipes[i]; if (pipe->is_handed_off) { pr_debug("Unmapping handed off pipe %d\n", pipe->num); - list_add(&pipe->cleanup_list, - &mdp5_data->pipes_cleanup); + list_add(&pipe->list, &mdp5_data->pipes_cleanup); mdss_mdp_mixer_pipe_unstage(pipe, pipe->mixer_left); pipe->is_handed_off = false; } @@ -1175,7 +1173,7 @@ static int __overlay_queue_pipes(struct msm_fb_data_type *mfd) struct mdss_mdp_ctl *tmp; int ret = 0; - list_for_each_entry(pipe, &mdp5_data->pipes_used, used_list) { + list_for_each_entry(pipe, &mdp5_data->pipes_used, list) { struct mdss_mdp_data *buf; /* * When secure display is enabled, if there is a non secure @@ -1268,12 +1266,12 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd, mutex_lock(ctl->shared_lock); mutex_lock(&mdp5_data->ov_lock); - mutex_lock(&mfd->lock); + mutex_lock(&mdp5_data->list_lock); /* * check if there is a secure display session */ - list_for_each_entry(pipe, &mdp5_data->pipes_used, used_list) { + list_for_each_entry(pipe, &mdp5_data->pipes_used, list) { if (pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) { sd_in_pipe = 1; pr_debug("Secure pipe: %u : %08X\n", @@ -1299,21 +1297,20 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd, * Setup pipe in solid fill before unstaging, * to ensure no fetches are happening after dettach or reattach. */ - list_for_each_entry(pipe, &mdp5_data->pipes_cleanup, cleanup_list) { + list_for_each_entry(pipe, &mdp5_data->pipes_cleanup, list) { mdss_mdp_pipe_queue_data(pipe, NULL); mdss_mdp_mixer_pipe_unstage(pipe, pipe->mixer_left); mdss_mdp_mixer_pipe_unstage(pipe, pipe->mixer_right); } ret = __overlay_queue_pipes(mfd); + mutex_unlock(&mdp5_data->list_lock); if (mfd->panel.type == WRITEBACK_PANEL) ret = mdss_mdp_wb_kickoff(mfd); else ret = mdss_mdp_display_commit(mdp5_data->ctl, NULL); - mutex_unlock(&mfd->lock); - if (IS_ERR_VALUE(ret)) goto commit_fail; @@ -1322,13 +1319,11 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd, ret = mdss_mdp_display_wait4comp(mdp5_data->ctl); if (ret == 0) { - mutex_lock(&mfd->lock); if (!mdp5_data->sd_enabled && sd_in_pipe) { ret = mdss_mdp_overlay_sd_ctrl(mfd, 1); if (ret == 0) mdp5_data->sd_enabled = 1; } - mutex_unlock(&mfd->lock); } mdss_fb_update_notify_update(mfd); @@ -1346,37 +1341,47 @@ commit_fail: static int mdss_mdp_overlay_release(struct msm_fb_data_type *mfd, int ndx) { - struct mdss_mdp_pipe *pipe; + struct mdss_mdp_pipe *pipe, *tmp; struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd); - u32 pipe_ndx, unset_ndx = 0; - int i, destroy_pipe; - - for (i = 0; unset_ndx != ndx && i < MDSS_MDP_MAX_SSPP; i++) { - pipe_ndx = BIT(i); - if (pipe_ndx & ndx) { - unset_ndx |= pipe_ndx; - pipe = mdss_mdp_pipe_get(mdp5_data->mdata, pipe_ndx); - if (IS_ERR_OR_NULL(pipe)) { - pr_warn("unknown pipe ndx=%x\n", pipe_ndx); + u32 unset_ndx = 0; + int destroy_pipe; + + mutex_lock(&mdp5_data->list_lock); + list_for_each_entry_safe(pipe, tmp, &mdp5_data->pipes_used, list) { + if (pipe->ndx & ndx) { + if (mdss_mdp_pipe_map(pipe)) { + pr_err("Unable to map used pipe%d ndx=%x\n", + pipe->num, pipe->ndx); continue; } - mutex_lock(&mfd->lock); + unset_ndx |= ndx; + pipe->pid = 0; destroy_pipe = pipe->play_cnt == 0; - if (!list_empty(&pipe->used_list)) { - list_del_init(&pipe->used_list); - if (!destroy_pipe) - list_add(&pipe->cleanup_list, + if (destroy_pipe) + list_del_init(&pipe->list); + else + list_move(&pipe->list, &mdp5_data->pipes_cleanup); - } - mutex_unlock(&mfd->lock); + mdss_mdp_pipe_unmap(pipe); if (destroy_pipe) mdss_mdp_pipe_destroy(pipe); + + if (unset_ndx == ndx) + break; } } + mutex_unlock(&mdp5_data->list_lock); + + if (unset_ndx != ndx) { + pr_warn("Unable to unset pipe(s) ndx=0x%x unset=0x%x\n", + ndx, unset_ndx); + return -ENOENT; + } + return 0; } @@ -1444,8 +1449,8 @@ static int __mdss_mdp_overlay_release_all(struct msm_fb_data_type *mfd, pr_debug("releasing all resources for fb%d pid=%d\n", mfd->index, pid); mutex_lock(&mdp5_data->ov_lock); - mutex_lock(&mfd->lock); - list_for_each_entry(pipe, &mdp5_data->pipes_used, used_list) { + mutex_lock(&mdp5_data->list_lock); + list_for_each_entry(pipe, &mdp5_data->pipes_used, list) { if (release_all || (pipe->pid == pid)) { unset_ndx |= pipe->ndx; cnt++; @@ -1461,7 +1466,7 @@ static int __mdss_mdp_overlay_release_all(struct msm_fb_data_type *mfd, pr_debug("release_all=%d mfd->ref_cnt=%d unset_ndx=0x%x cnt=%d\n", release_all, mfd->ref_cnt, unset_ndx, cnt); - mutex_unlock(&mfd->lock); + mutex_unlock(&mdp5_data->list_lock); if (unset_ndx) { pr_debug("%d pipes need cleanup (%x)\n", cnt, unset_ndx); @@ -3146,9 +3151,9 @@ static int mdss_mdp_overlay_off(struct msm_fb_data_type *mfd) if (mixer) mixer->cursor_enabled = 0; - mutex_lock(&mfd->lock); + mutex_lock(&mdp5_data->list_lock); need_cleanup = !list_empty(&mdp5_data->pipes_cleanup); - mutex_unlock(&mfd->lock); + mutex_unlock(&mdp5_data->list_lock); if (need_cleanup) { pr_debug("cleaning up pipes on fb%d\n", mfd->index); @@ -3503,6 +3508,7 @@ int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd) INIT_LIST_HEAD(&mdp5_data->pipes_used); INIT_LIST_HEAD(&mdp5_data->pipes_cleanup); INIT_LIST_HEAD(&mdp5_data->rot_proc_list); + mutex_init(&mdp5_data->list_lock); mutex_init(&mdp5_data->ov_lock); mdp5_data->hw_refresh = true; mdp5_data->overlay_play_enable = true; diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c index c8102ad34186fda044e8b82edcf72b10374a7a9c..11d82eb0889351a926a333ec0437df1b4cc7e4f3 100644 --- a/drivers/video/msm/mdss/mdss_mdp_pp.c +++ b/drivers/video/msm/mdss/mdss_mdp_pp.c @@ -1686,18 +1686,18 @@ int mdss_mdp_pp_setup(struct mdss_mdp_ctl *ctl) /* TODO: have some sort of reader/writer lock to prevent unclocked * access while display power is toggled */ - if (!ctl->mfd->panel_power_on) { + mutex_lock(&ctl->lock); + if (!ctl->power_on) { ret = -EPERM; goto error; } - mutex_lock(&ctl->mfd->lock); ret = mdss_mdp_pp_setup_locked(ctl); - mutex_unlock(&ctl->mfd->lock); error: + mutex_unlock(&ctl->lock); + return ret; } -/* call only when holding and mfd->lock */ int mdss_mdp_pp_setup_locked(struct mdss_mdp_ctl *ctl) { struct mdss_data_type *mdata = ctl->mdata; @@ -4768,10 +4768,10 @@ static void pp_ad_calc_worker(struct work_struct *work) ctl->remove_vsync_handler(ctl, &ad->handle); } mutex_unlock(&ad->lock); - mutex_lock(&mfd->lock); /* dspp3 doesn't have ad attached to it so following is safe */ + mutex_lock(&ctl->lock); ctl->flush_bits |= BIT(13 + ad->num); - mutex_unlock(&mfd->lock); + mutex_unlock(&ctl->lock); /* Trigger update notify to wake up those waiting for display updates */ mdss_fb_update_notify_update(bl_mfd);