From 7c9a3efa79d1b4b3576291f78e5551b16fc43032 Mon Sep 17 00:00:00 2001 From: Abhijit Kulkarni Date: Thu, 18 Aug 2016 12:19:20 -0700 Subject: [PATCH] msm: mdss: Enable secure display and camera feature for msmcobalt Add support for secure display and camera in driver. The physical address of the secure buffers is programmed into driver and hence there is no need of stage 1 translation. These changes handle the detach/attach of smmu contexts while going into and coming out of secure use case. For secure display both the secure and unsecure contexts are detached, while for secure camera only the secure context is detached. CRs-Fixed: 1085143 Change-Id: Iadab43e9655a9e97cdc6661c17a73891cbc2a17f Signed-off-by: Abhijit Kulkarni --- drivers/video/fbdev/msm/mdss.h | 13 ++ drivers/video/fbdev/msm/mdss_mdp.c | 119 +++++++++++++++-- drivers/video/fbdev/msm/mdss_mdp.h | 27 +++- drivers/video/fbdev/msm/mdss_mdp_debug.c | 2 +- drivers/video/fbdev/msm/mdss_mdp_layer.c | 43 ++++-- drivers/video/fbdev/msm/mdss_mdp_overlay.c | 144 ++++++++++++++------- drivers/video/fbdev/msm/mdss_mdp_pipe.c | 13 +- drivers/video/fbdev/msm/mdss_mdp_util.c | 15 ++- drivers/video/fbdev/msm/mdss_smmu.c | 37 +++++- drivers/video/fbdev/msm/mdss_smmu.h | 34 ++++- 10 files changed, 352 insertions(+), 95 deletions(-) diff --git a/drivers/video/fbdev/msm/mdss.h b/drivers/video/fbdev/msm/mdss.h index 1e93a5b2e9ba..5a24a1995af9 100644 --- a/drivers/video/fbdev/msm/mdss.h +++ b/drivers/video/fbdev/msm/mdss.h @@ -178,6 +178,7 @@ enum mdss_hw_capabilities { MDSS_CAPS_CWB_SUPPORTED, MDSS_CAPS_MDP_VOTE_CLK_NOT_SUPPORTED, MDSS_CAPS_AVR_SUPPORTED, + MDSS_CAPS_SEC_DETACH_SMMU, MDSS_CAPS_MAX, }; @@ -221,6 +222,7 @@ struct mdss_smmu_client { bool domain_attached; bool handoff_pending; void __iomem *mmu_base; + int domain; }; struct mdss_mdp_qseed3_lut_tbl { @@ -327,6 +329,7 @@ struct mdss_data_type { u32 wfd_mode; u32 has_no_lut_read; atomic_t sd_client_count; + atomic_t sc_client_count; u8 has_wb_ad; u8 has_non_scalar_rgb; bool has_src_split; @@ -519,6 +522,8 @@ struct mdss_data_type { u32 max_dest_scaler_input_width; u32 max_dest_scaler_output_width; struct mdss_mdp_destination_scaler *ds; + u32 sec_disp_en; + u32 sec_cam_en; }; extern struct mdss_data_type *mdss_res; @@ -579,6 +584,14 @@ static inline int mdss_get_sd_client_cnt(void) return atomic_read(&mdss_res->sd_client_count); } +static inline int mdss_get_sc_client_cnt(void) +{ + if (!mdss_res) + return 0; + else + return atomic_read(&mdss_res->sc_client_count); +} + static inline void mdss_set_quirk(struct mdss_data_type *mdata, enum mdss_hw_quirk bit) { diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c index 04e8fa4ba576..1dae41391795 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.c +++ b/drivers/video/fbdev/msm/mdss_mdp.c @@ -47,6 +47,8 @@ #include #include #include +#include "soc/qcom/secure_buffer.h" +#include #include "mdss.h" #include "mdss_fb.h" @@ -64,6 +66,8 @@ #define RES_1080p (1088*1920) #define RES_UHD (3840*2160) +#define MDP_DEVICE_ID 0x1A + struct mdss_data_type *mdss_res; static u32 mem_protect_sd_ctrl_id; @@ -87,6 +91,7 @@ struct msm_mdp_interface mdp5 = { #define MEM_PROTECT_SD_CTRL 0xF #define MEM_PROTECT_SD_CTRL_FLAT 0x14 +#define MEM_PROTECT_SD_CTRL_SWITCH 0x18 static DEFINE_SPINLOCK(mdp_lock); static DEFINE_SPINLOCK(mdss_mdp_intr_lock); @@ -1329,7 +1334,9 @@ int mdss_iommu_ctrl(int enable) if (mdata->iommu_ref_cnt == 0) { rc = mdss_smmu_detach(mdata); if (mdss_has_quirk(mdata, - MDSS_QUIRK_MIN_BUS_VOTE)) + MDSS_QUIRK_MIN_BUS_VOTE) && + (!mdata->sec_disp_en || + !mdata->sec_cam_en)) mdss_bus_scale_set_quota(MDSS_HW_RT, 0, 0); } @@ -1985,6 +1992,7 @@ static void mdss_mdp_hw_rev_caps_init(struct mdss_data_type *mdata) mdata->pixel_ram_size = 50 * 1024; mdata->rects_per_sspp[MDSS_MDP_PIPE_TYPE_DMA] = 2; + mem_protect_sd_ctrl_id = MEM_PROTECT_SD_CTRL_SWITCH; set_bit(MDSS_QOS_PER_PIPE_IB, mdata->mdss_qos_map); set_bit(MDSS_QOS_REMAPPER, mdata->mdss_qos_map); set_bit(MDSS_QOS_TS_PREFILL, mdata->mdss_qos_map); @@ -2015,6 +2023,7 @@ static void mdss_mdp_hw_rev_caps_init(struct mdss_data_type *mdata) mdata->has_wb_ubwc = true; set_bit(MDSS_CAPS_10_BIT_SUPPORTED, mdata->mdss_caps_map); set_bit(MDSS_CAPS_AVR_SUPPORTED, mdata->mdss_caps_map); + set_bit(MDSS_CAPS_SEC_DETACH_SMMU, mdata->mdss_caps_map); break; default: mdata->max_target_zorder = 4; /* excluding base layer */ @@ -4939,29 +4948,115 @@ static void mdss_mdp_footswitch_ctrl(struct mdss_data_type *mdata, int on) } } -int mdss_mdp_secure_display_ctrl(unsigned int enable) +int mdss_mdp_secure_session_ctrl(unsigned int enable, u64 flags) { + struct mdss_data_type *mdata = mdss_mdp_get_mdata(); struct sd_ctrl_req { unsigned int enable; } __attribute__ ((__packed__)) request; unsigned int resp = -1; int ret = 0; + uint32_t sid_info; struct scm_desc desc; - desc.args[0] = request.enable = enable; - desc.arginfo = SCM_ARGS(1); + if (test_bit(MDSS_CAPS_SEC_DETACH_SMMU, mdata->mdss_caps_map)) { + /* + * Prepare syscall to hypervisor to switch the secure_vmid + * between secure and non-secure contexts + */ + /* MDP secure SID */ + sid_info = 0x1; + desc.arginfo = SCM_ARGS(4, SCM_VAL, SCM_RW, SCM_VAL, SCM_VAL); + desc.args[0] = MDP_DEVICE_ID; + desc.args[1] = SCM_BUFFER_PHYS(&sid_info); + desc.args[2] = sizeof(uint32_t); - if (!is_scm_armv8()) { - ret = scm_call(SCM_SVC_MP, MEM_PROTECT_SD_CTRL, - &request, sizeof(request), &resp, sizeof(resp)); - } else { - ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP, + + pr_debug("Enable/Disable: %d, Flags %llx\n", enable, flags); + if (enable) { + if (flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) { + desc.args[3] = VMID_CP_SEC_DISPLAY; + mdata->sec_disp_en = 1; + } else if (flags & MDP_SECURE_CAMERA_OVERLAY_SESSION) { + desc.args[3] = VMID_CP_CAMERA_PREVIEW; + mdata->sec_cam_en = 1; + } else { + return 0; + } + + /* detach smmu contexts */ + ret = mdss_smmu_detach(mdata); + if (ret) { + pr_err("Error while detaching smmu contexts ret = %d\n", + ret); + return -EINVAL; + } + + /* let the driver think smmu is still attached */ + mdata->iommu_attached = true; + + dmac_flush_range(&sid_info, &sid_info + 1); + ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP, mem_protect_sd_ctrl_id), &desc); - resp = desc.ret[0]; - } + if (ret) { + pr_err("Error scm_call MEM_PROTECT_SD_CTRL(%u) ret=%dm resp=%x\n", + enable, ret, resp); + return -EINVAL; + } + resp = desc.ret[0]; - pr_debug("scm_call MEM_PROTECT_SD_CTRL(%u): ret=%d, resp=%x", + pr_debug("scm_call MEM_PROTECT_SD_CTRL(%u): ret=%d, resp=%x\n", + enable, ret, resp); + } else { + desc.args[3] = VMID_CP_PIXEL; + if (flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) + mdata->sec_disp_en = 0; + else if (flags & MDP_SECURE_CAMERA_OVERLAY_SESSION) + mdata->sec_cam_en = 0; + + dmac_flush_range(&sid_info, &sid_info + 1); + ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP, + mem_protect_sd_ctrl_id), &desc); + if (ret) + MDSS_XLOG_TOUT_HANDLER("mdp", "dsi0_ctrl", + "dsi0_phy", "dsi1_ctrl", + "dsi1_phy", "vbif", "vbif_nrt", + "dbg_bus", "vbif_dbg_bus", + "panic"); + resp = desc.ret[0]; + + pr_debug("scm_call MEM_PROTECT_SD_CTRL(%u): ret=%d, resp=%x\n", + enable, ret, resp); + + /* re-attach smmu contexts */ + mdata->iommu_attached = false; + ret = mdss_smmu_attach(mdata); + if (ret) { + pr_err("Error while attaching smmu contexts ret = %d\n", + ret); + return -EINVAL; + } + } + MDSS_XLOG(enable); + } else { + desc.args[0] = request.enable = enable; + desc.arginfo = SCM_ARGS(1); + + if (!is_scm_armv8()) { + ret = scm_call(SCM_SVC_MP, MEM_PROTECT_SD_CTRL, + &request, + sizeof(request), + &resp, + sizeof(resp)); + } else { + ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP, + mem_protect_sd_ctrl_id), &desc); + resp = desc.ret[0]; + } + + pr_debug("scm_call MEM_PROTECT_SD_CTRL(%u): ret=%d, resp=%x\n", enable, ret, resp); + } if (ret) return ret; diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h index 93f5f9a51a63..28fc78fdfa58 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.h +++ b/drivers/video/fbdev/msm/mdss_mdp.h @@ -92,6 +92,8 @@ */ #define ENABLE_PIXEL_EXT_ONLY 0x80000000 +/* Pipe flag to indicate this pipe contains secure camera buffer */ +#define MDP_SECURE_CAMERA_OVERLAY_SESSION 0x100000000 /** * Destination Scaler control flags setting * @@ -627,7 +629,7 @@ struct mdss_mdp_img_data { dma_addr_t addr; unsigned long len; u32 offset; - u32 flags; + u64 flags; u32 dir; u32 domain; bool mapped; @@ -811,7 +813,7 @@ struct mdss_mdp_pipe { struct file *file; bool is_handed_off; - u32 flags; + u64 flags; u32 bwc_mode; /* valid only when pipe's output is crossing both layer mixers */ @@ -916,6 +918,7 @@ struct mdss_overlay_private { u32 splash_mem_addr; u32 splash_mem_size; u32 sd_enabled; + u32 sc_enabled; struct sw_sync_timeline *vsync_timeline; struct mdss_mdp_vsync_handler vsync_retire_handler; @@ -1289,6 +1292,15 @@ static inline void mdss_update_sd_client(struct mdss_data_type *mdata, atomic_add_unless(&mdss_res->sd_client_count, -1, 0); } +static inline void mdss_update_sc_client(struct mdss_data_type *mdata, + bool status) +{ + if (status) + atomic_inc(&mdata->sc_client_count); + else + atomic_add_unless(&mdss_res->sc_client_count, -1, 0); +} + static inline int mdss_mdp_get_wb_ctl_support(struct mdss_data_type *mdata, bool rotator_session) { @@ -1506,6 +1518,7 @@ static inline bool mdss_mdp_is_map_needed(struct mdss_data_type *mdata, struct mdss_mdp_img_data *data) { u32 is_secure_ui = data->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION; + u64 is_secure_camera = data->flags & MDP_SECURE_CAMERA_OVERLAY_SESSION; /* * For ULT Targets we need SMMU Map, to issue map call for secure Display. @@ -1513,6 +1526,10 @@ static inline bool mdss_mdp_is_map_needed(struct mdss_data_type *mdata, if (is_secure_ui && !mdss_has_quirk(mdata, MDSS_QUIRK_NEED_SECURE_MAP)) return false; + if (is_secure_camera && test_bit(MDSS_CAPS_SEC_DETACH_SMMU, + mdata->mdss_caps_map)) + return false; + return true; } @@ -1569,7 +1586,7 @@ unsigned long mdss_mdp_get_clk_rate(u32 clk_idx, bool locked); int mdss_mdp_vsync_clk_enable(int enable, bool locked); void mdss_mdp_clk_ctrl(int enable); struct mdss_data_type *mdss_mdp_get_mdata(void); -int mdss_mdp_secure_display_ctrl(unsigned int enable); +int mdss_mdp_secure_session_ctrl(unsigned int enable, u64 flags); int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd); int mdss_mdp_dfps_update_params(struct msm_fb_data_type *mfd, @@ -1603,7 +1620,7 @@ int mdss_mdp_overlay_start(struct msm_fb_data_type *mfd); void mdss_mdp_overlay_set_chroma_sample( struct mdss_mdp_pipe *pipe); int mdp_pipe_tune_perf(struct mdss_mdp_pipe *pipe, - u32 flags); + u64 flags); int mdss_mdp_overlay_setup_scaling(struct mdss_mdp_pipe *pipe); struct mdss_mdp_pipe *mdss_mdp_pipe_assign(struct mdss_data_type *mdata, struct mdss_mdp_mixer *mixer, u32 ndx, @@ -1836,7 +1853,7 @@ struct mult_factor *mdss_mdp_get_comp_factor(u32 format, int mdss_mdp_data_map(struct mdss_mdp_data *data, bool rotator, int dir); void mdss_mdp_data_free(struct mdss_mdp_data *data, bool rotator, int dir); int mdss_mdp_data_get_and_validate_size(struct mdss_mdp_data *data, - struct msmfb_data *planes, int num_planes, u32 flags, + struct msmfb_data *planes, int num_planes, u64 flags, struct device *dev, bool rotator, int dir, struct mdp_layer_buffer *buffer); u32 mdss_get_panel_framerate(struct msm_fb_data_type *mfd); diff --git a/drivers/video/fbdev/msm/mdss_mdp_debug.c b/drivers/video/fbdev/msm/mdss_mdp_debug.c index 4c4fa9ea98d0..711d2d222c7d 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_debug.c +++ b/drivers/video/fbdev/msm/mdss_mdp_debug.c @@ -1868,7 +1868,7 @@ static void __dump_pipe(struct seq_file *s, struct mdss_mdp_pipe *pipe) int smps[4]; int i; - seq_printf(s, "\nSSPP #%d type=%s ndx=%x flags=0x%08x play_cnt=%u xin_id=%d\n", + seq_printf(s, "\nSSPP #%d type=%s ndx=%x flags=0x%16llx play_cnt=%u xin_id=%d\n", pipe->num, mdss_mdp_pipetype2str(pipe->type), pipe->ndx, pipe->flags, pipe->play_cnt, pipe->xin_id); seq_printf(s, "\tstage=%d alpha=0x%x transp=0x%x blend_op=%d\n", diff --git a/drivers/video/fbdev/msm/mdss_mdp_layer.c b/drivers/video/fbdev/msm/mdss_mdp_layer.c index 353d07ad64ac..eb110d166393 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_layer.c +++ b/drivers/video/fbdev/msm/mdss_mdp_layer.c @@ -936,7 +936,7 @@ static int __configure_pipe_params(struct msm_fb_data_type *mfd, { int ret = 0; u32 left_lm_w = left_lm_w_from_mfd(mfd); - u32 flags; + u64 flags; struct mdss_mdp_mixer *mixer = NULL; struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd); @@ -978,6 +978,8 @@ static int __configure_pipe_params(struct msm_fb_data_type *mfd, pipe->flags |= MDP_BWC_EN; if (layer->flags & MDP_LAYER_PP) pipe->flags |= MDP_OVERLAY_PP_CFG_EN; + if (layer->flags & MDP_LAYER_SECURE_CAMERA_SESSION) + pipe->flags |= MDP_SECURE_CAMERA_OVERLAY_SESSION; pipe->scaler.enable = (layer->flags & SCALER_ENABLED); pipe->is_fg = layer->flags & MDP_LAYER_FORGROUND; @@ -1348,7 +1350,7 @@ static struct mdss_mdp_data *__map_layer_buffer(struct msm_fb_data_type *mfd, struct mdp_layer_buffer *buffer; struct msmfb_data image; int i, ret; - u32 flags; + u64 flags; struct mdss_mdp_validate_info_t *vitem; for (i = 0; i < layer_count; i++) { @@ -1374,7 +1376,8 @@ static struct mdss_mdp_data *__map_layer_buffer(struct msm_fb_data_type *mfd, } flags = (pipe->flags & (MDP_SECURE_OVERLAY_SESSION | - MDP_SECURE_DISPLAY_OVERLAY_SESSION)); + MDP_SECURE_DISPLAY_OVERLAY_SESSION | + MDP_SECURE_CAMERA_OVERLAY_SESSION)); if (buffer->planes[0].fd < 0) { pr_err("invalid file descriptor for layer buffer\n"); @@ -1585,34 +1588,48 @@ end: } /* - * __validate_secure_display() - validate secure display + * __validate_secure_session() - validate various secure sessions * * This function travers through used pipe list and checks if any pipe - * is with secure display enabled flag. It fails if client tries to stage - * unsecure content with secure display session. + * is with secure display, secure video and secure camera enabled flag. + * It fails if client tries to stage unsecure content with + * secure display session and secure camera with secure video sessions. * */ -static int __validate_secure_display(struct mdss_overlay_private *mdp5_data) +static int __validate_secure_session(struct mdss_overlay_private *mdp5_data) { struct mdss_mdp_pipe *pipe, *tmp; uint32_t sd_pipes = 0, nonsd_pipes = 0; + uint32_t secure_vid_pipes = 0, secure_cam_pipes = 0; mutex_lock(&mdp5_data->list_lock); list_for_each_entry_safe(pipe, tmp, &mdp5_data->pipes_used, list) { if (pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) sd_pipes++; + else if (pipe->flags & MDP_SECURE_OVERLAY_SESSION) + secure_vid_pipes++; + else if (pipe->flags & MDP_SECURE_CAMERA_OVERLAY_SESSION) + secure_cam_pipes++; else nonsd_pipes++; } mutex_unlock(&mdp5_data->list_lock); - pr_debug("pipe count:: secure display:%d non-secure:%d\n", - sd_pipes, nonsd_pipes); + pr_debug("pipe count:: secure display:%d non-secure:%d secure-vid:%d,secure-cam:%d\n", + sd_pipes, nonsd_pipes, secure_vid_pipes, secure_cam_pipes); - if ((sd_pipes || mdss_get_sd_client_cnt()) && nonsd_pipes) { + if ((sd_pipes || mdss_get_sd_client_cnt()) && + (nonsd_pipes || secure_vid_pipes || + secure_cam_pipes)) { pr_err("non-secure layer validation request during secure display session\n"); - pr_err(" secure client cnt:%d secure pipe cnt:%d non-secure pipe cnt:%d\n", - mdss_get_sd_client_cnt(), sd_pipes, nonsd_pipes); + pr_err(" secure client cnt:%d secure pipe:%d non-secure pipe:%d, secure-vid:%d, secure-cam:%d\n", + mdss_get_sd_client_cnt(), sd_pipes, nonsd_pipes, + secure_vid_pipes, secure_cam_pipes); + return -EINVAL; + } else if (secure_cam_pipes && (secure_vid_pipes || sd_pipes)) { + pr_err(" incompatible layers during secure camera session\n"); + pr_err("secure-camera cnt:%d secure video:%d secure display:%d\n", + secure_cam_pipes, secure_vid_pipes, sd_pipes); return -EINVAL; } else { return 0; @@ -2388,7 +2405,7 @@ static int __validate_layers(struct msm_fb_data_type *mfd, validate_skip: __handle_free_list(mdp5_data, validate_info_list, layer_count); - ret = __validate_secure_display(mdp5_data); + ret = __validate_secure_session(mdp5_data); validate_exit: pr_debug("err=%d total_layer:%d left:%d right:%d rec0_rel_ndx=0x%x rec1_rel_ndx=0x%x rec0_destroy_ndx=0x%x rec1_destroy_ndx=0x%x processed=%d\n", diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c index 9bdc66232dd5..3860e679f75f 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c +++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c @@ -396,7 +396,7 @@ int mdss_mdp_overlay_req_check(struct msm_fb_data_type *mfd, } int mdp_pipe_tune_perf(struct mdss_mdp_pipe *pipe, - u32 flags) + u64 flags) { struct mdss_data_type *mdata = pipe->mixer_left->ctl->mdata; struct mdss_mdp_perf_params perf; @@ -1188,11 +1188,10 @@ static void __overlay_pipe_cleanup(struct msm_fb_data_type *mfd, list_move(&buf->buf_list, &mdp5_data->bufs_freelist); /* - * in case of secure UI, the buffer needs to be released as - * soon as session is closed. + * free the buffers on the same cycle instead of waiting for + * next kickoff */ - if (pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) - mdss_mdp_overlay_buf_free(mfd, buf); + mdss_mdp_overlay_buf_free(mfd, buf); } mdss_mdp_pipe_destroy(pipe); @@ -1477,7 +1476,7 @@ static int __overlay_queue_pipes(struct msm_fb_data_type *mfd) */ if (mdss_get_sd_client_cnt() && !(pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION)) { - pr_warn("Non secure pipe during secure display: %u: %08X, skip\n", + pr_warn("Non secure pipe during secure display: %u: %16llx, skip\n", pipe->num, pipe->flags); continue; } @@ -1957,6 +1956,92 @@ set_roi: mdss_mdp_set_roi(ctl, &l_roi, &r_roi); } +/* + * Enables/disable secure (display or camera) sessions + */ +static int __overlay_secure_ctrl(struct msm_fb_data_type *mfd) +{ + struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd); + struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd); + struct mdss_mdp_pipe *pipe; + int ret = 0; + int sd_in_pipe = 0; + int sc_in_pipe = 0; + + 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 : %16llx\n", + pipe->num, pipe->flags); + } else if (pipe->flags & MDP_SECURE_CAMERA_OVERLAY_SESSION) { + sc_in_pipe = 1; + pr_debug("Secure camera: %u: %16llx\n", + pipe->num, pipe->flags); + } + } + + if ((!sd_in_pipe && !mdp5_data->sd_enabled) || + (sd_in_pipe && mdp5_data->sd_enabled) || + (!sc_in_pipe && !mdp5_data->sc_enabled) || + (sc_in_pipe && mdp5_data->sc_enabled)) + return ret; + + /* Secure Display */ + if (!mdp5_data->sd_enabled && sd_in_pipe) { + if (!mdss_get_sd_client_cnt()) { + /*wait for ping pong done */ + if (ctl->ops.wait_pingpong) + mdss_mdp_display_wait4pingpong(ctl, true); + ret = mdss_mdp_secure_session_ctrl(1, + MDP_SECURE_DISPLAY_OVERLAY_SESSION); + if (ret) + return ret; + } + mdp5_data->sd_enabled = 1; + mdss_update_sd_client(mdp5_data->mdata, true); + } else if (mdp5_data->sd_enabled && !sd_in_pipe) { + /* disable the secure display on last client */ + if (mdss_get_sd_client_cnt() == 1) { + if (ctl->ops.wait_pingpong) + mdss_mdp_display_wait4pingpong(ctl, true); + ret = mdss_mdp_secure_session_ctrl(0, + MDP_SECURE_DISPLAY_OVERLAY_SESSION); + if (ret) + return ret; + } + mdss_update_sd_client(mdp5_data->mdata, false); + mdp5_data->sd_enabled = 0; + } + + /* Secure Camera */ + if (!mdp5_data->sc_enabled && sc_in_pipe) { + if (!mdss_get_sc_client_cnt()) { + if (ctl->ops.wait_pingpong) + mdss_mdp_display_wait4pingpong(ctl, true); + ret = mdss_mdp_secure_session_ctrl(1, + MDP_SECURE_CAMERA_OVERLAY_SESSION); + if (ret) + return ret; + } + mdp5_data->sc_enabled = 1; + mdss_update_sc_client(mdp5_data->mdata, true); + } else if (mdp5_data->sc_enabled && !sc_in_pipe) { + /* disable the secure camera on last client */ + if (mdss_get_sc_client_cnt() == 1) { + if (ctl->ops.wait_pingpong) + mdss_mdp_display_wait4pingpong(ctl, true); + ret = mdss_mdp_secure_session_ctrl(0, + MDP_SECURE_CAMERA_OVERLAY_SESSION); + if (ret) + return ret; + } + mdss_update_sc_client(mdp5_data->mdata, false); + mdp5_data->sc_enabled = 0; + } + + return ret; +} + int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd, struct mdp_display_commit *data) { @@ -1964,7 +2049,6 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd, struct mdss_mdp_pipe *pipe, *tmp; struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd); int ret = 0; - int sd_in_pipe = 0; struct mdss_mdp_commit_cb commit_cb; if (!ctl) @@ -1995,30 +2079,12 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd, mutex_unlock(ctl->shared_lock); return ret; } + mutex_lock(&mdp5_data->list_lock); - - /* - * check if there is a secure display session - */ - 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", - pipe->num, pipe->flags); - } - } - - /* - * start secure display session if there is secure display session and - * sd_enabled is not true. - */ - if (!mdp5_data->sd_enabled && sd_in_pipe) { - if (!mdss_get_sd_client_cnt()) - ret = mdss_mdp_secure_display_ctrl(1); - if (!ret) { - mdp5_data->sd_enabled = 1; - mdss_update_sd_client(mdp5_data->mdata, true); - } + ret = __overlay_secure_ctrl(mfd); + if (IS_ERR_VALUE(ret)) { + pr_err("secure operation failed %d\n", ret); + goto commit_fail; } if (!ctl->shared_lock) @@ -2108,19 +2174,6 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd, } mutex_lock(&mdp5_data->ov_lock); - /* - * If there is no secure display session and sd_enabled, disable the - * secure display session - */ - if (mdp5_data->sd_enabled && !sd_in_pipe && !ret) { - /* disable the secure display on last client */ - if (mdss_get_sd_client_cnt() == 1) - ret = mdss_mdp_secure_display_ctrl(0); - if (!ret) { - mdss_update_sd_client(mdp5_data->mdata, false); - mdp5_data->sd_enabled = 0; - } - } mdss_fb_update_notify_update(mfd); commit_fail: @@ -2272,7 +2325,7 @@ static int mdss_mdp_overlay_queue(struct msm_fb_data_type *mfd, struct mdss_mdp_data *src_data; struct mdp_layer_buffer buffer; int ret; - u32 flags; + u64 flags; pipe = __overlay_find_pipe(mfd, req->id); if (!pipe) { @@ -2298,7 +2351,8 @@ static int mdss_mdp_overlay_queue(struct msm_fb_data_type *mfd, pr_warn("Unexpected buffer queue to a solid fill pipe\n"); flags = (pipe->flags & (MDP_SECURE_OVERLAY_SESSION | - MDP_SECURE_DISPLAY_OVERLAY_SESSION)); + MDP_SECURE_DISPLAY_OVERLAY_SESSION | + MDP_SECURE_CAMERA_OVERLAY_SESSION)); mutex_lock(&mdp5_data->list_lock); src_data = mdss_mdp_overlay_buf_alloc(mfd, pipe); diff --git a/drivers/video/fbdev/msm/mdss_mdp_pipe.c b/drivers/video/fbdev/msm/mdss_mdp_pipe.c index 8f211a977aa4..7321ccdcfee9 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_pipe.c +++ b/drivers/video/fbdev/msm/mdss_mdp_pipe.c @@ -1878,7 +1878,8 @@ static void mdss_mdp_pipe_stride_update(struct mdss_mdp_pipe *pipe) if (pipe->multirect.mode == MDSS_MDP_PIPE_MULTIRECT_NONE) { memcpy(&ystride, &pipe->src_planes.ystride, sizeof(u32) * MAX_PLANES); - if (pipe->flags & MDP_SECURE_OVERLAY_SESSION) + if (pipe->flags & (MDP_SECURE_OVERLAY_SESSION | + MDP_SECURE_CAMERA_OVERLAY_SESSION)) secure = 0xF; } else { if (pipe->multirect.num == MDSS_MDP_PIPE_RECT0) { @@ -1891,12 +1892,14 @@ static void mdss_mdp_pipe_stride_update(struct mdss_mdp_pipe *pipe) ystride[0] = rec0_pipe->src_planes.ystride[0]; ystride[2] = rec0_pipe->src_planes.ystride[2]; - if (rec0_pipe->flags & MDP_SECURE_OVERLAY_SESSION) + if (rec0_pipe->flags & (MDP_SECURE_OVERLAY_SESSION | + MDP_SECURE_CAMERA_OVERLAY_SESSION)) secure |= 0x5; ystride[1] = rec1_pipe->src_planes.ystride[0]; ystride[3] = rec1_pipe->src_planes.ystride[2]; - if (rec1_pipe->flags & MDP_SECURE_OVERLAY_SESSION) + if (rec1_pipe->flags & (MDP_SECURE_OVERLAY_SESSION | + MDP_SECURE_CAMERA_OVERLAY_SESSION)) secure |= 0xA; } @@ -2320,7 +2323,9 @@ static int mdss_mdp_pipe_solidfill_setup(struct mdss_mdp_pipe *pipe) } format = MDSS_MDP_FMT_SOLID_FILL; - secure = (pipe->flags & MDP_SECURE_OVERLAY_SESSION ? 0xF : 0x0); + secure = (pipe->flags & (MDP_SECURE_OVERLAY_SESSION | + MDP_SECURE_CAMERA_OVERLAY_SESSION) + ? 0xF : 0x0); /* support ARGB color format only */ unpack = (C3_ALPHA << 24) | (C2_R_Cr << 16) | diff --git a/drivers/video/fbdev/msm/mdss_mdp_util.c b/drivers/video/fbdev/msm/mdss_mdp_util.c index 8b0ebc3fdf05..ffa99e72d152 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_util.c +++ b/drivers/video/fbdev/msm/mdss_mdp_util.c @@ -963,16 +963,17 @@ static int mdss_mdp_put_img(struct mdss_mdp_img_data *data, bool rotator, data->srcp_dma_buf = NULL; } } - } else if (data->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) { + } else if ((data->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) || + (data->flags & MDP_SECURE_CAMERA_OVERLAY_SESSION)) { /* - * skip memory unmapping - secure display uses physical - * address which does not require buffer unmapping + * skip memory unmapping - secure display and camera uses + * physical address which does not require buffer unmapping * * For LT targets in secure display usecase, srcp_dma_buf will * be filled due to map call which will be unmapped above. * */ - pr_debug("skip memory unmapping for secure display content\n"); + pr_debug("skip memory unmapping for secure display/camera content\n"); } else { return -ENOMEM; } @@ -1188,7 +1189,7 @@ err_unmap: } static int mdss_mdp_data_get(struct mdss_mdp_data *data, - struct msmfb_data *planes, int num_planes, u32 flags, + struct msmfb_data *planes, int num_planes, u64 flags, struct device *dev, bool rotator, int dir) { int i, rc = 0; @@ -1201,7 +1202,7 @@ static int mdss_mdp_data_get(struct mdss_mdp_data *data, rc = mdss_mdp_get_img(&planes[i], &data->p[i], dev, rotator, dir); if (rc) { - pr_err("failed to get buf p=%d flags=%x\n", i, flags); + pr_err("failed to get buf p=%d flags=%llx\n", i, flags); while (i > 0) { i--; mdss_mdp_put_img(&data->p[i], rotator, dir); @@ -1251,7 +1252,7 @@ void mdss_mdp_data_free(struct mdss_mdp_data *data, bool rotator, int dir) } int mdss_mdp_data_get_and_validate_size(struct mdss_mdp_data *data, - struct msmfb_data *planes, int num_planes, u32 flags, + struct msmfb_data *planes, int num_planes, u64 flags, struct device *dev, bool rotator, int dir, struct mdp_layer_buffer *buffer) { diff --git a/drivers/video/fbdev/msm/mdss_smmu.c b/drivers/video/fbdev/msm/mdss_smmu.c index eab7bcaaa156..2239791fdad0 100644 --- a/drivers/video/fbdev/msm/mdss_smmu.c +++ b/drivers/video/fbdev/msm/mdss_smmu.c @@ -162,12 +162,15 @@ end: } /* - * mdss_smmu_v2_attach() + * mdss_smmu_attach_v2() * * Associates each configured VA range with the corresponding smmu context * bank device. Enables the clks as smmu_v2 requires voting it before the usage. * And iommu attach is done only once during the initial attach and it is never * detached as smmu v2 uses a feature called 'retention'. + * Only detach the secure and non-secure contexts in case of secure display + * case and secure contexts for secure camera use cases for the platforms + * which have caps MDSS_CAPS_SEC_DETACH_SMMU enabled */ static int mdss_smmu_attach_v2(struct mdss_data_type *mdata) { @@ -191,7 +194,9 @@ static int mdss_smmu_attach_v2(struct mdss_data_type *mdata) } mdss_smmu->handoff_pending = false; - if (!mdss_smmu->domain_attached) { + if (!mdss_smmu->domain_attached && + mdss_smmu_is_valid_domain_condition(mdata, + i, true)) { rc = arm_iommu_attach_device(mdss_smmu->dev, mdss_smmu->mmu_mapping); if (rc) { @@ -229,10 +234,11 @@ err: } /* - * mdss_smmu_v2_detach() + * mdss_smmu_detach_v2() * - * Only disables the clks as it is not required to detach the iommu mapped - * VA range from the device in smmu_v2 as explained in the mdss_smmu_v2_attach + * Disables the clks only when it is not required to detach the iommu mapped + * VA range (as long as not in secure display use case) + * from the device in smmu_v2 as explained in the mdss_smmu_v2_attach */ static int mdss_smmu_detach_v2(struct mdss_data_type *mdata) { @@ -245,8 +251,24 @@ static int mdss_smmu_detach_v2(struct mdss_data_type *mdata) continue; mdss_smmu = mdss_smmu_get_cb(i); - if (mdss_smmu && mdss_smmu->dev && !mdss_smmu->handoff_pending) - mdss_smmu_enable_power(mdss_smmu, false); + if (mdss_smmu && mdss_smmu->dev) { + if (!mdss_smmu->handoff_pending && + mdss_smmu->domain_attached && + mdss_smmu_is_valid_domain_condition(mdata, + i, false)) { + /* + * if entering in secure display or + * secure camera use case(for secured contexts + * leave the smmu clocks on and only detach the + * smmu contexts + */ + arm_iommu_detach_device(mdss_smmu->dev); + mdss_smmu->domain_attached = false; + pr_debug("iommu v2 domain[%i] detached\n", i); + } else { + mdss_smmu_enable_power(mdss_smmu, false); + } + } } mutex_unlock(&mdp_iommu_lock); @@ -609,6 +631,7 @@ int mdss_smmu_probe(struct platform_device *pdev) } mdss_smmu = &mdata->mdss_smmu[smmu_domain.domain]; + mdss_smmu->domain = smmu_domain.domain; mp = &mdss_smmu->mp; memset(mp, 0, sizeof(struct dss_module_power)); diff --git a/drivers/video/fbdev/msm/mdss_smmu.h b/drivers/video/fbdev/msm/mdss_smmu.h index a987066cc773..f7e6e275c16a 100644 --- a/drivers/video/fbdev/msm/mdss_smmu.h +++ b/drivers/video/fbdev/msm/mdss_smmu.h @@ -73,6 +73,38 @@ static inline bool mdss_smmu_is_valid_domain_type(struct mdss_data_type *mdata, return true; } +static inline bool mdss_smmu_is_valid_domain_condition( + struct mdss_data_type *mdata, + int domain_type, + bool is_attach) +{ + if (is_attach) { + if (test_bit(MDSS_CAPS_SEC_DETACH_SMMU, + mdata->mdss_caps_map) && + (mdata->sec_disp_en || + (mdata->sec_cam_en && + domain_type == MDSS_IOMMU_DOMAIN_SECURE))) { + pr_debug("SMMU attach not attempted, sd:%d, sc:%d\n", + mdata->sec_disp_en, mdata->sec_cam_en); + return false; + } else { + return true; + } + } else { + if (test_bit(MDSS_CAPS_SEC_DETACH_SMMU, + mdata->mdss_caps_map) && + (mdata->sec_disp_en || + (mdata->sec_cam_en && + domain_type == MDSS_IOMMU_DOMAIN_SECURE))) { + pr_debug("SMMU detach attempted, sd:%d, sc:%d\n", + mdata->sec_disp_en, mdata->sec_cam_en); + return true; + } else { + return false; + } + } +} + static inline struct mdss_smmu_client *mdss_smmu_get_cb(u32 domain) { struct mdss_data_type *mdata = mdss_mdp_get_mdata(); @@ -96,7 +128,7 @@ static inline int is_mdss_iommu_attached(void) return mdata ? mdata->iommu_attached : false; } -static inline int mdss_smmu_get_domain_type(u32 flags, bool rotator) +static inline int mdss_smmu_get_domain_type(u64 flags, bool rotator) { struct mdss_data_type *mdata = mdss_mdp_get_mdata(); int type;