diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c index 42519be35aa9..abf20aef1256 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c @@ -621,9 +621,10 @@ static int sde_rotator_secure_session_ctrl(bool enable) if (mdata->wait_for_transition && mdata->secure_session_ctrl && mdata->callback_request) { ret = mdata->wait_for_transition(mdata->sec_cam_en, enable); - if (ret) { + if (ret < 0) { SDEROT_ERR("failed Secure wait for transition %d\n", ret); + ret = -EPERM; } else { if (mdata->sec_cam_en ^ enable) { mdata->sec_cam_en = enable; @@ -1114,6 +1115,8 @@ static int sde_rotator_assign_queue(struct sde_rot_mgr *mgr, if (IS_ERR_OR_NULL(hw)) { SDEROT_ERR("fail to allocate hw\n"); ret = PTR_ERR(hw); + if (!ret) + ret = -EINVAL; } else { queue->hw = hw; } diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c index 8157e8641e60..acb697946e18 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c @@ -1257,6 +1257,7 @@ err_put: data->srcp_dma_buf = NULL; imap_err: ion_free(rot->iclient, handle); + sde_smmu_ctrl(0); return rc; } @@ -1270,8 +1271,19 @@ static int sde_hw_rotator_swts_map(struct sde_hw_rotator *rot) { int rc = 0; struct sde_mdp_img_data *data = &rot->swts_buf; + struct sde_rot_data_type *mdata = sde_rot_get_mdata(); sde_smmu_ctrl(1); + if (mdata->wait_for_transition) { + rc = mdata->wait_for_transition(0, 0); + if (rc < 0) { + SDEROT_ERR("failed Secure wait for transition %d\n", + rc); + rc = -EPERM; + goto error; + } + } + rc = sde_smmu_map_dma_buf(data->srcp_dma_buf, data->srcp_table, SDE_IOMMU_DOMAIN_ROT_UNSECURE, &data->addr, &data->len, DMA_BIDIRECTIONAL); @@ -1291,7 +1303,7 @@ static int sde_hw_rotator_swts_map(struct sde_hw_rotator *rot) data->mapped = true; SDEROT_DBG("swts buffer mapped: %pad/%lx va:%p\n", &data->addr, - data->len, rot->swts_buffer); + data->len, rot->swts_buffer); sde_smmu_ctrl(0); return rc; @@ -1301,6 +1313,8 @@ kmap_err: err_unmap: dma_buf_unmap_attachment(data->srcp_attachment, data->srcp_table, DMA_FROM_DEVICE); +error: + sde_smmu_ctrl(0); return rc; } diff --git a/drivers/video/fbdev/msm/mdss_mdp_layer.c b/drivers/video/fbdev/msm/mdss_mdp_layer.c index b048f356c965..e44edb8fbea7 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_layer.c +++ b/drivers/video/fbdev/msm/mdss_mdp_layer.c @@ -1692,11 +1692,24 @@ static struct mdss_mdp_pipe *__find_and_move_cleanup_pipe( enum mdss_mdp_pipe_rect rect_num) { struct mdss_mdp_pipe *pipe = NULL; + struct mdss_mdp_data *buf, *tmpbuf; if (__find_pipe_in_list(&mdp5_data->pipes_destroy, pipe_ndx, &pipe, rect_num)) { pr_debug("reuse destroy pipe id:%d ndx:%d rect:%d\n", pipe->num, pipe_ndx, rect_num); + /* + * Pipe is being moved from destroy list to used list. + * It is possible that the buffer which was attached to a pipe + * in destroy list hasn't been cleaned up yet. Mark the buffers + * as cleanup to make sure that they will be freed before the + * pipe is reused. + */ + list_for_each_entry_safe(buf, tmpbuf, &pipe->buf_queue, + pipe_list) { + buf->state = MDP_BUF_STATE_CLEANUP; + list_del_init(&buf->pipe_list); + } list_move(&pipe->list, &mdp5_data->pipes_used); } else if (__find_pipe_in_list(&mdp5_data->pipes_cleanup, pipe_ndx, &pipe, rect_num)) { diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c index 91816611d24f..953aeb95332b 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c +++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c @@ -2317,6 +2317,31 @@ set_roi: mdss_mdp_set_roi(ctl, &l_roi, &r_roi); } +/* + * For the pipe which is being used for Secure Display, + * cleanup the previously queued buffers. + */ +static void __overlay_cleanup_secure_pipe(struct msm_fb_data_type *mfd) +{ + struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd); + struct mdss_mdp_pipe *pipe; + struct mdss_mdp_data *buf, *tmpbuf; + + list_for_each_entry(pipe, &mdp5_data->pipes_used, list) { + if (pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) { + list_for_each_entry_safe(buf, tmpbuf, &pipe->buf_queue, + pipe_list) { + if (buf->state == MDP_BUF_STATE_ACTIVE) { + __pipe_buf_mark_cleanup(mfd, buf); + list_move(&buf->buf_list, + &mdp5_data->bufs_freelist); + mdss_mdp_overlay_buf_free(mfd, buf); + } + } + } + } +} + /* * Check if there is any change in secure state and store it. */ @@ -2393,9 +2418,19 @@ static int __overlay_secure_ctrl(struct msm_fb_data_type *mfd) if (mdp5_data->secure_transition_state == SD_NON_SECURE_TO_SECURE) { if (!mdss_get_sd_client_cnt()) { MDSS_XLOG(0x11); - /*wait for ping pong done */ - if (ctl->ops.wait_pingpong) + /* wait for ping pong done */ + if (ctl->ops.wait_pingpong) { mdss_mdp_display_wait4pingpong(ctl, true); + + /* + * For command mode panels, there will not be + * a NULL commit preceding secure display. If + * a pipe is reused for secure display, + * cleanup buffers in the secure pipe before + * detaching IOMMU. + */ + __overlay_cleanup_secure_pipe(mfd); + } /* * unmap the previous commit buffers before * transitioning to secure state