diff options
| author | Adrian Salido-Moreno <adrianm@codeaurora.org> | 2013-10-15 20:31:50 -0700 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 20:22:29 -0700 |
| commit | 0df863c8161ca2e7d96211bbe7fb8e2aa18c890a (patch) | |
| tree | 1cf82199d7ef5a43b540dfaa75fb9a30b5947d08 /drivers/video/fbdev | |
| parent | 7201699f7e40a3fd6ab650eea9fdfb2dd7253025 (diff) | |
msm: mdss: implement display thread to handle commits
Refactor sync point implementation by using a commit thread to handle
all commits for better performance. Make use of commit count to
synchronize the release fences with the right point in the timeline.
Keep a separate commits pending variable to be able to queue multiple
commits as well.
Change-Id: I1303c49f2c56eb5b9a34c162a1896670d307a674
Signed-off-by: Adrian Salido-Moreno <adrianm@codeaurora.org>
Diffstat (limited to 'drivers/video/fbdev')
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_fb.c | 353 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_fb.h | 28 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_rotator.c | 8 |
3 files changed, 239 insertions, 150 deletions
diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c index 79291062bccc..731ada82b2c6 100644 --- a/drivers/video/fbdev/msm/mdss_fb.c +++ b/drivers/video/fbdev/msm/mdss_fb.c @@ -42,6 +42,7 @@ #include <linux/version.h> #include <linux/vmalloc.h> #include <linux/file.h> +#include <linux/kthread.h> #include <sync.h> #include <sw_sync.h> @@ -89,7 +90,7 @@ static int mdss_fb_ioctl(struct fb_info *info, unsigned int cmd, static int mdss_fb_mmap(struct fb_info *info, struct vm_area_struct *vma); static void mdss_fb_release_fences(struct msm_fb_data_type *mfd); -static void mdss_fb_commit_wq_handler(struct work_struct *work); +static int __mdss_fb_display_thread(void *data); static void mdss_fb_pan_idle(struct msm_fb_data_type *mfd); static int mdss_fb_send_panel_event(struct msm_fb_data_type *mfd, int event, void *arg); @@ -389,8 +390,6 @@ static int mdss_fb_probe(struct platform_device *pdev) if (mfd->mdp_sync_pt_data.timeline == NULL) { pr_err("%s: cannot create time line", __func__); return -ENOMEM; - } else { - mfd->mdp_sync_pt_data.timeline_value = 0; } } if (mfd->panel.type == WRITEBACK_PANEL) @@ -1108,6 +1107,8 @@ static int mdss_fb_register(struct msm_fb_data_type *mfd) mutex_init(&mfd->update.lock); mutex_init(&mfd->no_update.lock); mutex_init(&mfd->mdp_sync_pt_data.sync_mutex); + atomic_set(&mfd->mdp_sync_pt_data.commit_cnt, 0); + atomic_set(&mfd->commits_pending, 0); init_timer(&mfd->no_update.timer); mfd->no_update.timer.function = mdss_fb_no_update_notify_timer_cb; @@ -1115,15 +1116,9 @@ static int mdss_fb_register(struct msm_fb_data_type *mfd) init_completion(&mfd->update.comp); init_completion(&mfd->no_update.comp); init_completion(&mfd->power_off_comp); - init_completion(&mfd->commit_comp); init_completion(&mfd->power_set_comp); - INIT_WORK(&mfd->commit_work, mdss_fb_commit_wq_handler); - mfd->msm_fb_backup = kzalloc(sizeof(struct msm_fb_backup_type), - GFP_KERNEL); - if (mfd->msm_fb_backup == 0) { - pr_err("error: not enough memory!\n"); - return -ENOMEM; - } + init_waitqueue_head(&mfd->commit_wait_q); + init_waitqueue_head(&mfd->idle_wait_q); ret = fb_alloc_cmap(&fbi->cmap, 256, 0); if (ret) @@ -1140,9 +1135,14 @@ static int mdss_fb_register(struct msm_fb_data_type *mfd) mfd->index, fbi->var.xres, fbi->var.yres, fbi->fix.smem_len); - ret = 0; + mfd->disp_thread = kthread_run(__mdss_fb_display_thread, mfd, + "mdss_fb%d", mfd->index); + if (IS_ERR(mfd->disp_thread)) { + pr_err("unable to start display thread %d\n", mfd->index); + return PTR_ERR(mfd->disp_thread); + } - return ret; + return 0; } static int mdss_fb_open(struct fb_info *info, int user) @@ -1269,87 +1269,123 @@ static void mdss_fb_power_setting_idle(struct msm_fb_data_type *mfd) } } -void mdss_fb_wait_for_fence(struct msm_sync_pt_data *sync_pt_data) +int mdss_fb_wait_for_fence(struct msm_sync_pt_data *sync_pt_data) { + struct sync_fence *fences[MDP_MAX_FENCE_FD]; + int fence_cnt; int i, ret = 0; + + pr_debug("%s: wait for fences\n", sync_pt_data->fence_name); + + mutex_lock(&sync_pt_data->sync_mutex); + /* + * Assuming that acq_fen_cnt is sanitized in bufsync ioctl + * to check for sync_pt_data->acq_fen_cnt <= MDP_MAX_FENCE_FD + */ + fence_cnt = sync_pt_data->acq_fen_cnt; + sync_pt_data->acq_fen_cnt = 0; + if (fence_cnt) + memcpy(fences, sync_pt_data->acq_fen, + fence_cnt * sizeof(struct sync_fence *)); + mutex_unlock(&sync_pt_data->sync_mutex); + /* buf sync */ - for (i = 0; i < sync_pt_data->acq_fen_cnt; i++) { - ret = sync_fence_wait(sync_pt_data->acq_fen[i], + for (i = 0; i < fence_cnt && !ret; i++) { + ret = sync_fence_wait(fences[i], WAIT_FENCE_FIRST_TIMEOUT); if (ret == -ETIME) { - pr_warn("sync_fence_wait timed out! "); + pr_warn("%s: sync_fence_wait timed out! ", + sync_pt_data->fence_name); pr_cont("Waiting %ld more seconds\n", WAIT_FENCE_FINAL_TIMEOUT/MSEC_PER_SEC); - ret = sync_fence_wait(sync_pt_data->acq_fen[i], + ret = sync_fence_wait(fences[i], WAIT_FENCE_FINAL_TIMEOUT); } - if (ret < 0) { - pr_err("%s: sync_fence_wait failed! ret = %x\n", - __func__, ret); - break; - } - sync_fence_put(sync_pt_data->acq_fen[i]); + sync_fence_put(fences[i]); } if (ret < 0) { - while (i < sync_pt_data->acq_fen_cnt) { - sync_fence_put(sync_pt_data->acq_fen[i]); - i++; - } + pr_err("%s: sync_fence_wait failed! ret = %x\n", + sync_pt_data->fence_name, ret); + for (; i < fence_cnt; i++) + sync_fence_put(fences[i]); } - sync_pt_data->acq_fen_cnt = 0; -} -static void mdss_fb_signal_timeline_locked( - struct msm_sync_pt_data *sync_pt_data) -{ - if (sync_pt_data->timeline && !list_empty((const struct list_head *) - (&(sync_pt_data->timeline->obj.active_list_head)))) { - sw_sync_timeline_inc(sync_pt_data->timeline, 1); - sync_pt_data->timeline_value++; - } - sync_pt_data->cur_rel_fence = 0; + return fence_cnt; } +/** + * mdss_fb_signal_timeline() - signal a single release fence + * @sync_pt_data: Sync point data structure for the timeline which + * should be signaled. + * + * This is called after a frame has been pushed to display. This signals the + * timeline to release the fences associated with this frame. + */ void mdss_fb_signal_timeline(struct msm_sync_pt_data *sync_pt_data) { mutex_lock(&sync_pt_data->sync_mutex); - mdss_fb_signal_timeline_locked(sync_pt_data); + if (atomic_add_unless(&sync_pt_data->commit_cnt, -1, 0) && + sync_pt_data->timeline) { + sw_sync_timeline_inc(sync_pt_data->timeline, 1); + sync_pt_data->timeline_value++; + + pr_debug("%s: buffer signaled! timeline val=%d remaining=%d\n", + sync_pt_data->fence_name, sync_pt_data->timeline_value, + atomic_read(&sync_pt_data->commit_cnt)); + } else { + pr_debug("%s timeline signaled without commits val=%d\n", + sync_pt_data->fence_name, sync_pt_data->timeline_value); + } mutex_unlock(&sync_pt_data->sync_mutex); } +/** + * mdss_fb_release_fences() - signal all pending release fences + * @mfd: Framebuffer data structure for display + * + * Release all currently pending release fences, including those that are in + * the process to be commited. + * + * Note: this should only be called during close or suspend sequence. + */ static void mdss_fb_release_fences(struct msm_fb_data_type *mfd) { + struct msm_sync_pt_data *sync_pt_data = &mfd->mdp_sync_pt_data; + int val; - mutex_lock(&mfd->mdp_sync_pt_data.sync_mutex); - if (mfd->mdp_sync_pt_data.timeline) { - sw_sync_timeline_inc(mfd->mdp_sync_pt_data.timeline, 2); - mfd->mdp_sync_pt_data.timeline_value += 2; + mutex_lock(&sync_pt_data->sync_mutex); + if (sync_pt_data->timeline) { + val = sync_pt_data->threshold + + atomic_read(&sync_pt_data->commit_cnt); + sw_sync_timeline_inc(sync_pt_data->timeline, val); + sync_pt_data->timeline_value += val; + atomic_set(&sync_pt_data->commit_cnt, 0); } - mfd->mdp_sync_pt_data.cur_rel_fence = 0; - mutex_unlock(&mfd->mdp_sync_pt_data.sync_mutex); + mutex_unlock(&sync_pt_data->sync_mutex); } + +/** + * mdss_fb_pan_idle() - wait for panel programming to be idle + * @mfd: Framebuffer data structure for display + * + * Wait for any pending programming to be done if in the process of programming + * hardware configuration. After this function returns it is safe to perform + * software updates for next frame. + */ static void mdss_fb_pan_idle(struct msm_fb_data_type *mfd) { int ret; - if (mfd->is_committing) { - ret = wait_for_completion_timeout( - &mfd->commit_comp, + ret = wait_event_timeout(mfd->idle_wait_q, + !atomic_read(&mfd->commits_pending), msecs_to_jiffies(WAIT_DISP_OP_TIMEOUT)); - if (ret < 0) - ret = -ERESTARTSYS; - else if (!ret) - pr_err("%s wait for commit_comp timeout %d %d", - __func__, ret, mfd->is_committing); - if (ret <= 0) { - mutex_lock(&mfd->mdp_sync_pt_data.sync_mutex); - mdss_fb_signal_timeline_locked(&mfd->mdp_sync_pt_data); - mfd->is_committing = 0; - complete_all(&mfd->commit_comp); - mutex_unlock(&mfd->mdp_sync_pt_data.sync_mutex); - } + if (!ret) { + pr_err("wait for idle timeout %d pending=%d\n", + ret, atomic_read(&mfd->commits_pending)); + + mdss_fb_signal_timeline(&mfd->mdp_sync_pt_data); } } @@ -1357,7 +1393,6 @@ static int mdss_fb_pan_display_ex(struct fb_info *info, struct mdp_display_commit *disp_commit) { struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; - struct msm_fb_backup_type *fb_backup; struct fb_var_screeninfo *var = &disp_commit->var; u32 wait_for_finish = disp_commit->wait_for_finish; int ret = 0; @@ -1382,13 +1417,12 @@ static int mdss_fb_pan_display_ex(struct fb_info *info, info->var.yoffset = (var->yoffset / info->fix.ypanstep) * info->fix.ypanstep; - fb_backup = (struct msm_fb_backup_type *)mfd->msm_fb_backup; - memcpy(&fb_backup->info, info, sizeof(struct fb_info)); - memcpy(&fb_backup->disp_commit, disp_commit, - sizeof(struct mdp_display_commit)); - INIT_COMPLETION(mfd->commit_comp); - mfd->is_committing = 1; - schedule_work(&mfd->commit_work); + mfd->msm_fb_backup.info = *info; + mfd->msm_fb_backup.disp_commit = *disp_commit; + + atomic_inc(&mfd->mdp_sync_pt_data.commit_cnt); + atomic_inc(&mfd->commits_pending); + wake_up_all(&mfd->commit_wait_q); mutex_unlock(&mfd->mdp_sync_pt_data.sync_mutex); if (wait_for_finish) mdss_fb_pan_idle(mfd); @@ -1427,14 +1461,12 @@ static int mdss_fb_pan_display_sub(struct fb_var_screeninfo *var, info->var.yoffset = (var->yoffset / info->fix.ypanstep) * info->fix.ypanstep; - mdss_fb_wait_for_fence(&mfd->mdp_sync_pt_data); if (mfd->mdp.dma_fnc) mfd->mdp.dma_fnc(mfd); else pr_warn("dma function not set for panel type=%d\n", mfd->panel.type); - mdss_fb_signal_timeline(&mfd->mdp_sync_pt_data); - mdss_fb_update_backlight(mfd); + return 0; } @@ -1452,36 +1484,59 @@ static void mdss_fb_var_to_panelinfo(struct fb_var_screeninfo *var, pinfo->clk_rate = var->pixclock; } -static void mdss_fb_commit_wq_handler(struct work_struct *work) +/** + * __mdss_fb_perform_commit() - process a frame to display + * @mfd: Framebuffer data structure for display + * + * Processes all layers and buffers programmed and ensures all pending release + * fences are signaled once the buffer is transfered to display. + */ +static int __mdss_fb_perform_commit(struct msm_fb_data_type *mfd) { - struct msm_fb_data_type *mfd; - struct fb_var_screeninfo *var; - struct fb_info *info; - struct msm_fb_backup_type *fb_backup; - int ret = 0; + struct msm_sync_pt_data *sync_pt_data = &mfd->mdp_sync_pt_data; + struct msm_fb_backup_type *fb_backup = &mfd->msm_fb_backup; + int ret = -ENOSYS; + + mdss_fb_wait_for_fence(sync_pt_data); - mfd = container_of(work, struct msm_fb_data_type, commit_work); - fb_backup = (struct msm_fb_backup_type *)mfd->msm_fb_backup; - info = &fb_backup->info; - if (fb_backup->disp_commit.flags & - MDP_DISPLAY_COMMIT_OVERLAY) { - mdss_fb_wait_for_fence(&mfd->mdp_sync_pt_data); + if (fb_backup->disp_commit.flags & MDP_DISPLAY_COMMIT_OVERLAY) { if (mfd->mdp.kickoff_fnc) ret = mfd->mdp.kickoff_fnc(mfd, - &fb_backup->disp_commit); - if (!ret) - mdss_fb_update_backlight(mfd); - mdss_fb_signal_timeline(&mfd->mdp_sync_pt_data); + &fb_backup->disp_commit); + else + pr_warn("no kickoff function setup for fb%d\n", + mfd->index); } else { - var = &fb_backup->disp_commit.var; - ret = mdss_fb_pan_display_sub(var, info); + ret = mdss_fb_pan_display_sub(&fb_backup->disp_commit.var, + &fb_backup->info); if (ret) - pr_err("%s fails: ret = %x", __func__, ret); + pr_err("pan display failed %x on fb%d\n", ret, + mfd->index); } - mutex_lock(&mfd->mdp_sync_pt_data.sync_mutex); - mfd->is_committing = 0; - complete_all(&mfd->commit_comp); - mutex_unlock(&mfd->mdp_sync_pt_data.sync_mutex); + if (!ret) + mdss_fb_update_backlight(mfd); + + mdss_fb_signal_timeline(sync_pt_data); + + return ret; +} + +static int __mdss_fb_display_thread(void *data) +{ + struct msm_fb_data_type *mfd = data; + int ret; + + while (1) { + wait_event(mfd->commit_wait_q, + atomic_read(&mfd->commits_pending)); + + ret = __mdss_fb_perform_commit(mfd); + + atomic_dec(&mfd->commits_pending); + wake_up_all(&mfd->idle_wait_q); + } + + return ret; } static int mdss_fb_check_var(struct fb_var_screeninfo *var, @@ -1753,12 +1808,52 @@ static int mdss_fb_set_lut(struct fb_info *info, void __user *p) return 0; } +/** + * mdss_fb_sync_get_rel_fence() - get release fence from sync pt timeline + * @sync_pt_data: Sync pt structure holding timeline and fence info. + * + * Function returns a release fence on the timeline associated with the + * sync pt struct given and it's associated information. The release fence + * created can be used to signal when buffers provided will be released. + */ +static struct sync_fence *__mdss_fb_sync_get_rel_fence( + struct msm_sync_pt_data *sync_pt_data) +{ + struct sync_pt *rel_sync_pt; + struct sync_fence *rel_fence; + int val; + + val = sync_pt_data->timeline_value + sync_pt_data->threshold + + atomic_read(&sync_pt_data->commit_cnt); + + pr_debug("%s: buf sync rel fence timeline=%d\n", + sync_pt_data->fence_name, val); + + rel_sync_pt = sw_sync_pt_create(sync_pt_data->timeline, val); + if (rel_sync_pt == NULL) { + pr_err("%s: cannot create sync point\n", + sync_pt_data->fence_name); + return NULL; + } + + /* create fence */ + rel_fence = sync_fence_create(sync_pt_data->fence_name, rel_sync_pt); + if (rel_fence == NULL) { + sync_pt_free(rel_sync_pt); + pr_err("%s: cannot create fence\n", sync_pt_data->fence_name); + return NULL; + } + + return rel_fence; +} + static int mdss_fb_handle_buf_sync_ioctl(struct msm_sync_pt_data *sync_pt_data, struct mdp_buf_sync *buf_sync) { int i, ret = 0; int acq_fen_fd[MDP_MAX_FENCE_FD]; - struct sync_fence *fence; + struct sync_fence *fence, *rel_fence; + int rel_fen_fd; if ((buf_sync->acq_fen_fd_cnt > MDP_MAX_FENCE_FD) || (sync_pt_data->timeline == NULL)) @@ -1768,16 +1863,22 @@ static int mdss_fb_handle_buf_sync_ioctl(struct msm_sync_pt_data *sync_pt_data, ret = copy_from_user(acq_fen_fd, buf_sync->acq_fen_fd, buf_sync->acq_fen_fd_cnt * sizeof(int)); if (ret) { - pr_err("%s:copy_from_user failed", __func__); + pr_err("%s: copy_from_user failed", sync_pt_data->fence_name); return ret; } + i = mdss_fb_wait_for_fence(sync_pt_data); + if (i > 0) + pr_warn("%s: waited on %d active fences\n", + sync_pt_data->fence_name, i); + mutex_lock(&sync_pt_data->sync_mutex); for (i = 0; i < buf_sync->acq_fen_fd_cnt; i++) { fence = sync_fence_fdget(acq_fen_fd[i]); if (fence == NULL) { - pr_info("%s: null fence! i=%d fd=%d\n", __func__, i, - acq_fen_fd[i]); + pr_err("%s: null fence! i=%d fd=%d\n", + sync_pt_data->fence_name, i, + acq_fen_fd[i]); ret = -EINVAL; break; } @@ -1787,54 +1888,40 @@ static int mdss_fb_handle_buf_sync_ioctl(struct msm_sync_pt_data *sync_pt_data, if (ret) goto buf_sync_err_1; - if (buf_sync->flags & MDP_BUF_SYNC_FLAG_WAIT) - mdss_fb_wait_for_fence(sync_pt_data); - - sync_pt_data->cur_rel_sync_pt = sw_sync_pt_create( - sync_pt_data->timeline, sync_pt_data->timeline_value + - sync_pt_data->threshold); - - if (sync_pt_data->cur_rel_sync_pt == NULL) { - pr_err("%s: cannot create sync point", __func__); - ret = -ENOMEM; - goto buf_sync_err_1; - } - /* create fence */ - sync_pt_data->cur_rel_fence = sync_fence_create( - sync_pt_data->fence_name, sync_pt_data->cur_rel_sync_pt); - - if (sync_pt_data->cur_rel_fence == NULL) { - sync_pt_free(sync_pt_data->cur_rel_sync_pt); - sync_pt_data->cur_rel_sync_pt = NULL; - pr_err("%s: cannot create fence", __func__); - ret = -ENOMEM; + rel_fence = __mdss_fb_sync_get_rel_fence(sync_pt_data); + if (IS_ERR_OR_NULL(rel_fence)) { + pr_err("%s: unable to retrieve release fence\n", + sync_pt_data->fence_name); + ret = rel_fence ? PTR_ERR(rel_fence) : -ENOMEM; goto buf_sync_err_1; } + /* create fd */ - sync_pt_data->cur_rel_fen_fd = get_unused_fd_flags(0); - if (sync_pt_data->cur_rel_fen_fd < 0) { - pr_err("%s: get_unused_fd_flags failed", __func__); - ret = -EIO; + rel_fen_fd = get_unused_fd_flags(0); + if (rel_fen_fd < 0) { + pr_err("%s: get_unused_fd_flags failed\n", + sync_pt_data->fence_name); + ret = -EIO; goto buf_sync_err_2; } - sync_fence_install(sync_pt_data->cur_rel_fence, - sync_pt_data->cur_rel_fen_fd); - ret = copy_to_user(buf_sync->rel_fen_fd, - &sync_pt_data->cur_rel_fen_fd, sizeof(int)); + sync_fence_install(rel_fence, rel_fen_fd); + ret = copy_to_user(buf_sync->rel_fen_fd, &rel_fen_fd, sizeof(int)); if (ret) { - pr_err("%s:copy_to_user failed", __func__); + pr_err("%s: copy_to_user failed\n", sync_pt_data->fence_name); goto buf_sync_err_3; } mutex_unlock(&sync_pt_data->sync_mutex); + + if (buf_sync->flags & MDP_BUF_SYNC_FLAG_WAIT) + mdss_fb_wait_for_fence(sync_pt_data); + return ret; buf_sync_err_3: - put_unused_fd(sync_pt_data->cur_rel_fen_fd); + put_unused_fd(rel_fen_fd); buf_sync_err_2: - sync_fence_put(sync_pt_data->cur_rel_fence); - sync_pt_data->cur_rel_fence = NULL; - sync_pt_data->cur_rel_fen_fd = 0; + sync_fence_put(rel_fence); buf_sync_err_1: for (i = 0; i < sync_pt_data->acq_fen_cnt; i++) sync_fence_put(sync_pt_data->acq_fen[i]); diff --git a/drivers/video/fbdev/msm/mdss_fb.h b/drivers/video/fbdev/msm/mdss_fb.h index 8611bc5c3882..8d1099376ce8 100644 --- a/drivers/video/fbdev/msm/mdss_fb.h +++ b/drivers/video/fbdev/msm/mdss_fb.h @@ -60,12 +60,12 @@ struct msm_sync_pt_data { char *fence_name; u32 acq_fen_cnt; struct sync_fence *acq_fen[MDP_MAX_FENCE_FD]; - int cur_rel_fen_fd; - struct sync_pt *cur_rel_sync_pt; - struct sync_fence *cur_rel_fence; + struct sw_sync_timeline *timeline; int timeline_value; u32 threshold; + + atomic_t commit_cnt; struct mutex sync_mutex; }; @@ -108,6 +108,11 @@ struct mdss_fb_proc_info { struct list_head list; }; +struct msm_fb_backup_type { + struct fb_info info; + struct mdp_display_commit disp_commit; +}; + struct msm_fb_data_type { u32 key; u32 index; @@ -162,10 +167,12 @@ struct msm_fb_data_type { struct msm_sync_pt_data mdp_sync_pt_data; /* for non-blocking */ - struct completion commit_comp; - u32 is_committing; - struct work_struct commit_work; - void *msm_fb_backup; + struct task_struct *disp_thread; + atomic_t commits_pending; + wait_queue_head_t commit_wait_q; + wait_queue_head_t idle_wait_q; + + struct msm_fb_backup_type msm_fb_backup; struct completion power_set_comp; u32 is_power_setting; @@ -173,11 +180,6 @@ struct msm_fb_data_type { struct list_head proc_list; }; -struct msm_fb_backup_type { - struct fb_info info; - struct mdp_display_commit disp_commit; -}; - static inline void mdss_fb_update_notify_update(struct msm_fb_data_type *mfd) { int needs_complete = 0; @@ -200,7 +202,7 @@ static inline void mdss_fb_update_notify_update(struct msm_fb_data_type *mfd) int mdss_fb_get_phys_info(dma_addr_t *start, unsigned long *len, int fb_num); void mdss_fb_set_backlight(struct msm_fb_data_type *mfd, u32 bkl_lvl); void mdss_fb_update_backlight(struct msm_fb_data_type *mfd); -void mdss_fb_wait_for_fence(struct msm_sync_pt_data *sync_pt_data); +int mdss_fb_wait_for_fence(struct msm_sync_pt_data *sync_pt_data); void mdss_fb_signal_timeline(struct msm_sync_pt_data *sync_pt_data); int mdss_fb_register_mdp_instance(struct msm_mdp_interface *mdp); int mdss_fb_dcm(struct msm_fb_data_type *mfd, int req_state); diff --git a/drivers/video/fbdev/msm/mdss_mdp_rotator.c b/drivers/video/fbdev/msm/mdss_mdp_rotator.c index c6d5bc21484f..6ce8f924bc72 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_rotator.c +++ b/drivers/video/fbdev/msm/mdss_mdp_rotator.c @@ -277,12 +277,12 @@ static void mdss_mdp_rotator_commit_wq_handler(struct work_struct *work) int ret; rot = container_of(work, struct mdss_mdp_rotator_session, commit_work); - ret = mdss_mdp_rotator_queue_helper(rot); - if (ret) { + atomic_inc(&rot->rot_sync_pt_data->commit_cnt); + + ret = mdss_mdp_rotator_queue_helper(rot); + if (ret) pr_err("rotator queue failed\n"); - return; - } if (rot->rot_sync_pt_data) mdss_fb_signal_timeline(rot->rot_sync_pt_data); |
