summaryrefslogtreecommitdiff
path: root/drivers/video/fbdev/msm
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2017-01-05 02:09:02 -0800
committerGerrit - the friendly Code Review server <code-review@localhost>2017-01-05 02:09:01 -0800
commit8b24b9db96640895ecc5683358ec9986fdbcd96d (patch)
treed2bfc3cabf4c5cd888bc217829769d6ffa74317f /drivers/video/fbdev/msm
parentc4ae5b86905067e6f95683a229de12e2b0c45395 (diff)
parentaeb892b900c87a46035d7a77ad0eb26a8dd0c17f (diff)
Merge "msm: mdss: fix cwb output buffer memory leak"
Diffstat (limited to 'drivers/video/fbdev/msm')
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.h1
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_ctl.c5
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_overlay.c15
3 files changed, 21 insertions, 0 deletions
diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h
index 3bb936638a12..d3d332d780d5 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.h
+++ b/drivers/video/fbdev/msm/mdss_mdp.h
@@ -424,6 +424,7 @@ struct mdss_mdp_ctl_intfs_ops {
struct mdss_mdp_cwb {
struct mutex queue_lock;
struct list_head data_queue;
+ struct list_head cleanup_queue;
int valid;
u32 wb_idx;
struct mdp_output_layer layer;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
index e7b54617c6e6..5246e5d1166c 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
@@ -3565,6 +3565,11 @@ int mdss_mdp_cwb_setup(struct mdss_mdp_ctl *ctl)
goto cwb_setup_fail;
}
+ /* Add to cleanup list */
+ mutex_lock(&cwb->queue_lock);
+ list_add_tail(&cwb_data->next, &mdp5_data->cwb.cleanup_queue);
+ mutex_unlock(&cwb->queue_lock);
+
memset(&wb_args, 0, sizeof(wb_args));
wb_args.data = &cwb_data->data;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
index 64a8d0833362..8f48956680fc 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
@@ -5873,10 +5873,24 @@ __vsync_retire_get_fence(struct msm_sync_pt_data *sync_pt_data)
static void __cwb_wq_handler(struct work_struct *cwb_work)
{
struct mdss_mdp_cwb *cwb = NULL;
+ struct mdss_mdp_wb_data *cwb_data = NULL;
cwb = container_of(cwb_work, struct mdss_mdp_cwb, cwb_work);
blocking_notifier_call_chain(&cwb->notifier_head,
MDP_NOTIFY_FRAME_DONE, NULL);
+
+ /* free the buffer from cleanup queue */
+ mutex_lock(&cwb->queue_lock);
+ cwb_data = list_first_entry_or_null(&cwb->cleanup_queue,
+ struct mdss_mdp_wb_data, next);
+ __list_del_entry(&cwb_data->next);
+ mutex_unlock(&cwb->queue_lock);
+ if (cwb_data == NULL) {
+ pr_err("no output buffer for cwb cleanup\n");
+ return;
+ }
+ mdss_mdp_data_free(&cwb_data->data, true, DMA_FROM_DEVICE);
+ kfree(cwb_data);
}
static int __vsync_set_vsync_handler(struct msm_fb_data_type *mfd)
@@ -6107,6 +6121,7 @@ int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd)
mutex_init(&mdp5_data->cwb.queue_lock);
mutex_init(&mdp5_data->cwb.cwb_sync_pt_data.sync_mutex);
INIT_LIST_HEAD(&mdp5_data->cwb.data_queue);
+ INIT_LIST_HEAD(&mdp5_data->cwb.cleanup_queue);
snprintf(timeline_name, sizeof(timeline_name), "cwb%d", mfd->index);
mdp5_data->cwb.cwb_sync_pt_data.fence_name = "cwb-fence";