summaryrefslogtreecommitdiff
path: root/drivers/video
diff options
context:
space:
mode:
authorVeera Sundaram Sankaran <veeras@codeaurora.org>2016-05-05 19:03:54 -0700
committerKyle Yan <kyan@codeaurora.org>2016-07-05 15:31:41 -0700
commit2bb0363c03e989ab64618f7112d76e7a828d5d6e (patch)
treeab800dd25de225a90864e7c1e01f13b4f12919e8 /drivers/video
parent95eadad55b28aaaa92b02698ed3600dc06eb6d24 (diff)
msm: mdss: handle used_buf during overlay off with invalid switch state
There might be cases where driver gets the resolution switch request followed by suspend or adb shell stop. In such cases, since the ctl parameters are already reconfigured, driver skips the NULL kickoff during overlay off due to invalid switch state. This leads to memory leak as the used_bufs are left intact. Fix by moving the used_bufs to free_list, so that memory can be freed later and also leaves the buffer list clean. Change-Id: I80c6ad2dc85da0427ac7ba1c127f0aa044a81c09 Signed-off-by: Veera Sundaram Sankaran <veeras@codeaurora.org>
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_overlay.c35
1 files changed, 34 insertions, 1 deletions
diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
index a6f85c6deda8..457c5462c44f 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
@@ -4880,6 +4880,39 @@ static void mdss_mdp_set_lm_flag(struct msm_fb_data_type *mfd)
}
}
+static void mdss_mdp_handle_invalid_switch_state(struct msm_fb_data_type *mfd)
+{
+ int rc = 0;
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+ struct mdss_mdp_ctl *ctl = mdp5_data->ctl;
+ struct mdss_mdp_ctl *sctl = mdss_mdp_get_split_ctl(ctl);
+ struct mdss_mdp_data *buf, *tmpbuf;
+
+ mfd->switch_state = MDSS_MDP_NO_UPDATE_REQUESTED;
+
+ /*
+ * Handle only for cmd mode panels as for video mode, buffers
+ * cannot be freed at this point. Needs revisting to handle the
+ * use case for video mode panels.
+ */
+ if (mfd->panel_info->type == MIPI_CMD_PANEL) {
+ if (ctl->ops.wait_pingpong)
+ rc = ctl->ops.wait_pingpong(ctl, NULL);
+ if (!rc && sctl && sctl->ops.wait_pingpong)
+ rc = sctl->ops.wait_pingpong(sctl, NULL);
+ if (rc) {
+ pr_err("wait for pp failed\n");
+ return;
+ }
+
+ mutex_lock(&mdp5_data->list_lock);
+ list_for_each_entry_safe(buf, tmpbuf,
+ &mdp5_data->bufs_used, buf_list)
+ list_move(&buf->buf_list, &mdp5_data->bufs_freelist);
+ mutex_unlock(&mdp5_data->list_lock);
+ }
+}
+
static int mdss_mdp_overlay_on(struct msm_fb_data_type *mfd)
{
int rc;
@@ -5064,7 +5097,7 @@ static int mdss_mdp_overlay_off(struct msm_fb_data_type *mfd)
need_cleanup = false;
pr_warn("fb%d blank while mode switch (%d) in progress\n",
mfd->index, mfd->switch_state);
- mfd->switch_state = MDSS_MDP_NO_UPDATE_REQUESTED;
+ mdss_mdp_handle_invalid_switch_state(mfd);
}
mutex_unlock(&mfd->switch_lock);