From cbd1c43d5a8ae87d5f4671f02c4b0a9a27cbd895 Mon Sep 17 00:00:00 2001 From: Abhijit Kulkarni Date: Mon, 26 Sep 2016 22:32:10 -0700 Subject: [PATCH] msm: sde: secure camera changes for v4l2 rotator Add support for secure camera buffer handling in SDE rotator. This change adds detaching the secure context when the buffer with the secure camera flag is signaled and attaches the secure context when going back to normal non securer-camera usecases. Change-Id: Iaff45907e78775975fa3035404dcfd9b27e6e816 Signed-off-by: Abhijit Kulkarni --- .../msm/sde/rotator/sde_rotator_base.c | 9 ++ .../msm/sde/rotator/sde_rotator_base.h | 5 + .../msm/sde/rotator/sde_rotator_core.c | 107 +++++++++++++ .../msm/sde/rotator/sde_rotator_core.h | 3 + .../msm/sde/rotator/sde_rotator_dev.c | 57 +++++-- .../msm/sde/rotator/sde_rotator_dev.h | 3 + .../platform/msm/sde/rotator/sde_rotator_r3.c | 20 +-- .../msm/sde/rotator/sde_rotator_r3_internal.h | 1 + .../msm/sde/rotator/sde_rotator_smmu.c | 75 ++++++++- .../msm/sde/rotator/sde_rotator_smmu.h | 2 + .../msm/sde/rotator/sde_rotator_util.c | 143 +++++++++++++----- .../msm/sde/rotator/sde_rotator_util.h | 6 + include/uapi/media/msm_sde_rotator.h | 6 + 13 files changed, 376 insertions(+), 61 deletions(-) diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c index bc153ff8ac2c..5e763f74170e 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c @@ -560,6 +560,15 @@ int sde_rotator_base_init(struct sde_rot_data_type **pmdata, goto probe_done; } + mdata->iclient = msm_ion_client_create(mdata->pdev->name); + if (IS_ERR_OR_NULL(mdata->iclient)) { + SDEROT_ERR("msm_ion_client_create() return error (%pK)\n", + mdata->iclient); + mdata->iclient = NULL; + rc = -EFAULT; + goto probe_done; + } + *pmdata = mdata; return 0; diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h index 67c6b11329d8..80da9b4cfcb6 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h @@ -83,6 +83,7 @@ enum sde_caps_settings { SDE_CAPS_R1_WB, SDE_CAPS_R3_WB, SDE_CAPS_R3_1P5_DOWNSCALE, + SDE_CAPS_SEC_ATTACH_DETACH_SMMU, SDE_CAPS_MAX, }; @@ -111,6 +112,7 @@ struct sde_smmu_client { struct sde_module_power mp; struct reg_bus_client *reg_bus_clt; bool domain_attached; + int domain; }; struct sde_rot_vbif_debug_bus { @@ -169,6 +171,9 @@ struct sde_rot_data_type { u32 regdump_size; void *sde_rot_hw; + int sec_cam_en; + + struct ion_client *iclient; }; int sde_rotator_base_init(struct sde_rot_data_type **pmdata, 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 dc5a5a0dc851..09c2dc6c237f 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c @@ -25,6 +25,10 @@ #include #include #include +#include +#include +#include +#include #include "sde_rotator_base.h" #include "sde_rotator_core.h" @@ -37,6 +41,18 @@ #include "sde_rotator_trace.h" #include "sde_rotator_debug.h" + +/* Rotator device id to be used in SCM call */ +#define SDE_ROTATOR_DEVICE 21 + +/* SCM call function id to be used for switching between secure and non + * secure context + */ +#define MEM_PROTECT_SD_CTRL_SWITCH 0x18 + +/* Rotator secure SID */ +#define SDE_ROTATOR_SECURE_SID 0xe01 + /* waiting for hw time out, 3 vsync for 30fps*/ #define ROT_HW_ACQUIRE_TIMEOUT_IN_MS 100 @@ -505,6 +521,7 @@ static int sde_rotator_import_buffer(struct sde_layer_buffer *buffer, planes[i].memory_id = buffer->planes[i].fd; planes[i].offset = buffer->planes[i].offset; planes[i].buffer = buffer->planes[i].buffer; + planes[i].handle = buffer->planes[i].handle; } ret = sde_mdp_data_get_and_validate_size(data, planes, @@ -513,6 +530,86 @@ static int sde_rotator_import_buffer(struct sde_layer_buffer *buffer, return ret; } +static int sde_rotator_secure_session_ctrl(struct sde_rot_entry *entry) +{ + struct sde_rot_data_type *mdata = sde_rot_get_mdata(); + uint32_t sid_info; + struct scm_desc desc; + unsigned int resp = 0; + int ret = 0; + + if (test_bit(SDE_CAPS_SEC_ATTACH_DETACH_SMMU, + mdata->sde_caps_map)) { + sid_info = SDE_ROTATOR_SECURE_SID; + desc.arginfo = SCM_ARGS(4, SCM_VAL, SCM_RW, SCM_VAL, SCM_VAL); + desc.args[0] = SDE_ROTATOR_DEVICE; + desc.args[1] = SCM_BUFFER_PHYS(&sid_info); + desc.args[2] = sizeof(uint32_t); + + if (!mdata->sec_cam_en && + (entry->item.flags & SDE_ROTATION_SECURE_CAMERA)) { + /* + * Enable secure camera operation + * Send SCM call to hypervisor to switch the + * secure_vmid to secure context + */ + desc.args[3] = VMID_CP_CAMERA_PREVIEW; + + mdata->sec_cam_en = 1; + sde_smmu_secure_ctrl(0); + + dmac_flush_range(&sid_info, &sid_info + 1); + ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP, + MEM_PROTECT_SD_CTRL_SWITCH), &desc); + resp = desc.ret[0]; + if (ret) { + SDEROT_ERR("scm_call(1) ret=%d, resp=%x\n", + ret, resp); + /* failure, attach smmu */ + mdata->sec_cam_en = 0; + sde_smmu_secure_ctrl(1); + return -EINVAL; + } + + SDEROT_DBG("scm_call(1) ret=%d, resp=%x", + ret, resp); + SDEROT_EVTLOG(1, entry->item.flags, + entry->src_buf.p[0].addr, + entry->dst_buf.p[0].addr); + } else if (mdata->sec_cam_en && !(entry->item.flags & + SDE_ROTATION_SECURE_CAMERA)) { + /* + * Disable secure camera operation + * Send SCM call to hypervisor to switch the + * secure_vmid to non-secure context + */ + desc.args[3] = VMID_CP_PIXEL; + 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_SWITCH), &desc); + resp = desc.ret[0]; + + SDEROT_DBG("scm_call(0): ret=%d, resp=%x", + ret, resp); + + /* force smmu to reattach */ + sde_smmu_secure_ctrl(1); + SDEROT_EVTLOG(0, entry->item.flags, + entry->src_buf.p[0].addr, + entry->dst_buf.p[0].addr); + } + } else { + return 0; + } + if (ret) + return ret; + + return resp; +} + + static int sde_rotator_map_and_check_data(struct sde_rot_entry *entry) { int ret; @@ -531,6 +628,13 @@ static int sde_rotator_map_and_check_data(struct sde_rot_entry *entry) if (IS_ERR_VALUE(ret)) return ret; + ret = sde_rotator_secure_session_ctrl(entry); + if (ret) { + SDEROT_ERR("failed secure session enabling/disabling %d\n", + ret); + goto end; + } + /* if error during map, the caller will release the data */ ret = sde_mdp_data_map(&entry->src_buf, true, DMA_TO_DEVICE); if (ret) { @@ -642,6 +746,9 @@ static int sde_rotator_import_data(struct sde_rot_mgr *mgr, if (entry->item.flags & SDE_ROTATION_EXT_DMA_BUF) flag |= SDE_ROT_EXT_DMA_BUF; + if (entry->item.flags & SDE_ROTATION_SECURE_CAMERA) + flag |= SDE_SECURE_CAMERA_SESSION; + ret = sde_rotator_import_buffer(input, &entry->src_buf, flag, &mgr->pdev->dev, true); if (ret) { diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h index e1b326b8eb1c..eca0cbefcab1 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h @@ -59,6 +59,9 @@ Rotation request flag /* use client provided dma buf instead of ion fd */ #define SDE_ROTATION_EXT_DMA_BUF 0x20000 +/* secure camera operation*/ +#define SDE_ROTATION_SECURE_CAMERA 0x40000 + /********************************************************************** configuration structures **********************************************************************/ diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c index 08075ae90507..a3815fac8169 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c @@ -90,6 +90,8 @@ static uint32_t sde_rotator_get_flags_from_ctx(struct sde_rotator_ctx *ctx) ret_flags ^= SDE_ROTATION_FLIP_UD; if (ctx->secure) ret_flags |= SDE_ROTATION_SECURE; + if (ctx->secure_camera) + ret_flags |= SDE_ROTATION_SECURE_CAMERA; if (ctx->format_out.fmt.pix.field == V4L2_FIELD_INTERLACED && ctx->format_cap.fmt.pix.field == V4L2_FIELD_NONE) ret_flags |= SDE_ROTATION_DEINTERLACE; @@ -510,28 +512,45 @@ static void *sde_rotator_get_userptr(void *alloc_ctx, struct sde_rotator_ctx *ctx = alloc_ctx; struct sde_rotator_device *rot_dev = ctx->rot_dev; struct sde_rotator_buf_handle *buf; + struct ion_client *iclient = rot_dev->mdata->iclient; buf = kzalloc(sizeof(*buf), GFP_KERNEL); if (!buf) return ERR_PTR(-ENOMEM); buf->fd = vaddr; - buf->secure = ctx->secure; + buf->secure = ctx->secure || ctx->secure_camera; buf->ctx = ctx; buf->rot_dev = rot_dev; - buf->buffer = dma_buf_get(buf->fd); - - if (IS_ERR_OR_NULL(buf->buffer)) { - SDEDEV_ERR(rot_dev->dev, "fail get dmabuf fd:%d r:%ld\n", + if (ctx->secure_camera) { + buf->handle = ion_import_dma_buf(iclient, + buf->fd); + if (IS_ERR_OR_NULL(buf->handle)) { + SDEDEV_ERR(rot_dev->dev, + "fail get ion_handler fd:%d r:%ld\n", buf->fd, PTR_ERR(buf->buffer)); - goto error_dma_buf_get; + goto error_buf_get; + } + SDEDEV_DBG(rot_dev->dev, + "get ion_handle s:%d fd:%d buf:%pad\n", + buf->ctx->session_id, + buf->fd, &buf->handle); + } else { + buf->buffer = dma_buf_get(buf->fd); + if (IS_ERR_OR_NULL(buf->buffer)) { + SDEDEV_ERR(rot_dev->dev, + "fail get dmabuf fd:%d r:%ld\n", + buf->fd, PTR_ERR(buf->buffer)); + goto error_buf_get; + } + SDEDEV_DBG(rot_dev->dev, + "get dmabuf s:%d fd:%d buf:%pad\n", + buf->ctx->session_id, + buf->fd, &buf->buffer); } - SDEDEV_DBG(rot_dev->dev, "get dmabuf s:%d fd:%d buf:%pad\n", - buf->ctx->session_id, - buf->fd, &buf->buffer); return buf; -error_dma_buf_get: +error_buf_get: kfree(buf); return ERR_PTR(-ENOMEM); } @@ -618,6 +637,9 @@ static int sde_rotator_s_ctrl(struct v4l2_ctrl *ctrl) ret = sde_rotator_s_ctx_ctrl(ctx, &ctx->secure, ctrl); break; + case V4L2_CID_SDE_ROTATOR_SECURE_CAMERA: + ret = sde_rotator_s_ctx_ctrl(ctx, &ctx->secure_camera, ctrl); + break; default: v4l2_warn(&rot_dev->v4l2_dev, "invalid control %d\n", ctrl->id); ret = -EINVAL; @@ -648,6 +670,17 @@ static const struct v4l2_ctrl_config sde_rotator_ctrl_secure = { .step = 1, }; +static const struct v4l2_ctrl_config sde_rotator_ctrl_secure_camera = { + .ops = &sde_rotator_ctrl_ops, + .id = V4L2_CID_SDE_ROTATOR_SECURE_CAMERA, + .name = "Secure Camera content", + .type = V4L2_CTRL_TYPE_INTEGER, + .def = 0, + .min = 0, + .max = 1, + .step = 1, +}; + /* * sde_rotator_ctx_show - show context state. */ @@ -924,6 +957,8 @@ static int sde_rotator_open(struct file *file) &sde_rotator_ctrl_ops, V4L2_CID_ROTATE, 0, 270, 90, 0); v4l2_ctrl_new_custom(ctrl_handler, &sde_rotator_ctrl_secure, NULL); + v4l2_ctrl_new_custom(ctrl_handler, + &sde_rotator_ctrl_secure_camera, NULL); if (ctrl_handler->error) { ret = ctrl_handler->error; v4l2_ctrl_handler_free(ctrl_handler); @@ -2010,11 +2045,13 @@ static int sde_rotator_process_buffers(struct sde_rotator_ctx *ctx, sde_rotator_get_item_from_ctx(ctx, &item); item.flags |= SDE_ROTATION_EXT_DMA_BUF; item.input.planes[0].buffer = src_handle->buffer; + item.input.planes[0].handle = src_handle->handle; item.input.planes[0].offset = src_handle->addr; item.input.planes[0].stride = ctx->format_out.fmt.pix.bytesperline; item.input.plane_count = 1; item.input.fence = NULL; item.output.planes[0].buffer = dst_handle->buffer; + item.output.planes[0].handle = dst_handle->handle; item.output.planes[0].offset = dst_handle->addr; item.output.planes[0].stride = ctx->format_cap.fmt.pix.bytesperline; item.output.plane_count = 1; diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.h index f3c904817296..e6fe1e487755 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.h +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.h @@ -48,6 +48,7 @@ struct sde_rotator_ctx; * @addr: Address of rotator mmu mapped buffer. * @secure: Non-secure/secure buffer. * @buffer: Pointer to dma buf associated with this fd. + * @ihandle: ion handle associated with this fd */ struct sde_rotator_buf_handle { int fd; @@ -57,6 +58,7 @@ struct sde_rotator_buf_handle { ion_phys_addr_t addr; int secure; struct dma_buf *buffer; + struct ion_handle *handle; }; /* @@ -119,6 +121,7 @@ struct sde_rotator_ctx { s32 vflip; s32 rotate; s32 secure; + s32 secure_camera; atomic_t command_pending; int abort_pending; int nbuf_cap; 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 eaf35733b38a..cecdb1411d11 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c @@ -641,7 +641,8 @@ static void sde_hw_rotator_setup_fetchengine(struct sde_hw_rotator_context *ctx, ((rot->highest_bank & 0x3) << 18)); /* setup source buffer plane security status */ - if (flags & SDE_ROT_FLAG_SECURE_OVERLAY_SESSION) { + if (flags & (SDE_ROT_FLAG_SECURE_OVERLAY_SESSION | + SDE_ROT_FLAG_SECURE_CAMERA_SESSION)) { SDE_REGDMA_WRITE(wrptr, ROT_SSPP_SRC_ADDR_SW_STATUS, 0xF); ctx->is_secure = true; } else { @@ -739,7 +740,8 @@ static void sde_hw_rotator_setup_wbengine(struct sde_hw_rotator_context *ctx, SDE_REGDMA_WRITE(wrptr, ROT_WB_OUT_XY, cfg->dst_rect->x | (cfg->dst_rect->y << 16)); - if (flags & SDE_ROT_FLAG_SECURE_OVERLAY_SESSION) + if (flags & (SDE_ROT_FLAG_SECURE_OVERLAY_SESSION | + SDE_ROT_FLAG_SECURE_CAMERA_SESSION)) SDE_REGDMA_WRITE(wrptr, ROT_WB_DST_ADDR_SW_STATUS, 0x1); else SDE_REGDMA_WRITE(wrptr, ROT_WB_DST_ADDR_SW_STATUS, 0); @@ -1131,14 +1133,10 @@ static int sde_hw_rotator_swts_create(struct sde_hw_rotator *rot) int rc = 0; struct ion_handle *handle; struct sde_mdp_img_data *data; + struct sde_rot_data_type *mdata = sde_rot_get_mdata(); u32 bufsize = sizeof(int) * SDE_HW_ROT_REGDMA_TOTAL_CTX * 2; - rot->iclient = msm_ion_client_create(rot->pdev->name); - if (IS_ERR_OR_NULL(rot->iclient)) { - SDEROT_ERR("msm_ion_client_create() return error (%p)\n", - rot->iclient); - return -EINVAL; - } + rot->iclient = mdata->iclient; handle = ion_alloc(rot->iclient, bufsize, SZ_4K, ION_HEAP(ION_SYSTEM_HEAP_ID), 0); @@ -1564,6 +1562,9 @@ static int sde_hw_rotator_config(struct sde_rot_hw_resource *hw, SDE_ROT_FLAG_DEINTERLACE : 0; flags |= (item->flags & SDE_ROTATION_SECURE) ? SDE_ROT_FLAG_SECURE_OVERLAY_SESSION : 0; + flags |= (item->flags & SDE_ROTATION_SECURE_CAMERA) ? + SDE_ROT_FLAG_SECURE_CAMERA_SESSION : 0; + sspp_cfg.img_width = item->input.width; sspp_cfg.img_height = item->input.height; @@ -1808,13 +1809,14 @@ static int sde_rotator_hw_rev_init(struct sde_hw_rotator *rot) set_bit(SDE_CAPS_R3_1P5_DOWNSCALE, mdata->sde_caps_map); } + set_bit(SDE_CAPS_SEC_ATTACH_DETACH_SMMU, mdata->sde_caps_map); + mdata->nrt_vbif_dbg_bus = nrt_vbif_dbg_bus_r3; mdata->nrt_vbif_dbg_bus_size = ARRAY_SIZE(nrt_vbif_dbg_bus_r3); mdata->regdump = sde_rot_r3_regdump; mdata->regdump_size = ARRAY_SIZE(sde_rot_r3_regdump); - SDE_ROTREG_WRITE(rot->mdss_base, REGDMA_TIMESTAMP_REG, 0); return 0; } diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h index 7aecc3cee210..e666f4811c77 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h @@ -28,6 +28,7 @@ struct sde_hw_rotator_context; #define SDE_ROT_FLAG_SOURCE_ROTATED_90 0x8 #define SDE_ROT_FLAG_ROT_90 0x10 #define SDE_ROT_FLAG_DEINTERLACE 0x20 +#define SDE_ROT_FLAG_SECURE_CAMERA_SESSION 0x40 /** * General defines diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_smmu.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_smmu.c index c11c4b61d832..50d21a13425a 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_smmu.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_smmu.c @@ -51,6 +51,30 @@ static inline bool sde_smmu_is_valid_domain_type( return true; } +static inline bool sde_smmu_is_valid_domain_condition( + struct sde_rot_data_type *mdata, + int domain_type, + bool is_attach) +{ + if (is_attach) { + if (test_bit(SDE_CAPS_SEC_ATTACH_DETACH_SMMU, + mdata->sde_caps_map) && + (mdata->sec_cam_en && + domain_type == SDE_IOMMU_DOMAIN_ROT_SECURE)) + return false; + else + return true; + } else { + if (test_bit(SDE_CAPS_SEC_ATTACH_DETACH_SMMU, + mdata->sde_caps_map) && + (mdata->sec_cam_en && + domain_type == SDE_IOMMU_DOMAIN_ROT_SECURE)) + return true; + else + return false; + } +} + struct sde_smmu_client *sde_smmu_get_cb(u32 domain) { struct sde_rot_data_type *mdata = sde_rot_get_mdata(); @@ -180,7 +204,7 @@ end: * And iommu attach is done only once during the initial attach and it is never * detached as smmu v2 uses a feature called 'retention'. */ -static int sde_smmu_attach(struct sde_rot_data_type *mdata) +int sde_smmu_attach(struct sde_rot_data_type *mdata) { struct sde_smmu_client *sde_smmu; int i, rc = 0; @@ -199,7 +223,10 @@ static int sde_smmu_attach(struct sde_rot_data_type *mdata) goto err; } - if (!sde_smmu->domain_attached) { + if (!sde_smmu->domain_attached && + sde_smmu_is_valid_domain_condition(mdata, + i, + true)) { rc = arm_iommu_attach_device(sde_smmu->dev, sde_smmu->mmu_mapping); if (rc) { @@ -240,7 +267,7 @@ err: * Only disables the clks as it is not required to detach the iommu mapped * VA range from the device in smmu as explained in the sde_smmu_attach */ -static int sde_smmu_detach(struct sde_rot_data_type *mdata) +int sde_smmu_detach(struct sde_rot_data_type *mdata) { struct sde_smmu_client *sde_smmu; int i; @@ -250,8 +277,18 @@ static int sde_smmu_detach(struct sde_rot_data_type *mdata) continue; sde_smmu = sde_smmu_get_cb(i); - if (sde_smmu && sde_smmu->dev) - sde_smmu_enable_power(sde_smmu, false); + if (sde_smmu && sde_smmu->dev) { + if (sde_smmu->domain_attached && + sde_smmu_is_valid_domain_condition(mdata, + i, false)) { + arm_iommu_detach_device(sde_smmu->dev); + SDEROT_DBG("iommu domain[%i] detached\n", i); + sde_smmu->domain_attached = false; + } + else { + sde_smmu_enable_power(sde_smmu, false); + } + } } return 0; } @@ -367,6 +404,33 @@ int sde_smmu_ctrl(int enable) return mdata->iommu_ref_cnt; } +int sde_smmu_secure_ctrl(int enable) +{ + struct sde_rot_data_type *mdata = sde_rot_get_mdata(); + int rc = 0; + + mutex_lock(&sde_smmu_ref_cnt_lock); + /* + * Attach/detach secure context irrespective of ref count, + * We come here only when secure camera is disabled + */ + if (enable) { + rc = sde_smmu_attach(mdata); + if (!rc) + mdata->iommu_attached = true; + } else { + rc = sde_smmu_detach(mdata); + /* + * keep iommu_attached equal to true, + * so that driver does not attemp to attach + * while in secure state + */ + } + + mutex_unlock(&sde_smmu_ref_cnt_lock); + return rc; +} + /* * sde_smmu_device_create() * @dev: sde_mdp device @@ -476,6 +540,7 @@ int sde_smmu_probe(struct platform_device *pdev) } sde_smmu = &mdata->sde_smmu[smmu_domain.domain]; + sde_smmu->domain = smmu_domain.domain; mp = &sde_smmu->mp; memset(mp, 0, sizeof(struct sde_module_power)); diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_smmu.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_smmu.h index 1adcfb7310f2..4a1c3d323143 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_smmu.h +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_smmu.h @@ -45,4 +45,6 @@ int sde_smmu_map_dma_buf(struct dma_buf *dma_buf, void sde_smmu_unmap_dma_buf(struct sg_table *table, int domain, int dir, struct dma_buf *dma_buf); +int sde_smmu_secure_ctrl(int enable); + #endif /* SDE_ROTATOR_SMMU_H */ diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_util.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_util.c index 60c4c81eddf2..fb7bb37d52d9 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_util.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_util.c @@ -745,6 +745,13 @@ static int sde_mdp_put_img(struct sde_mdp_img_data *data, bool rotator, return 0; } +static int sde_mdp_is_map_needed(struct sde_mdp_img_data *data) +{ + if (data->flags & SDE_SECURE_CAMERA_SESSION) + return false; + return true; +} + static int sde_mdp_get_img(struct sde_fb_data *img, struct sde_mdp_img_data *data, struct device *dev, bool rotator, int dir) @@ -753,6 +760,8 @@ static int sde_mdp_get_img(struct sde_fb_data *img, unsigned long *len; u32 domain; dma_addr_t *start; + struct sde_rot_data_type *mdata = sde_rot_get_mdata(); + struct ion_client *iclient = mdata->iclient; start = &data->addr; len = &data->len; @@ -766,35 +775,79 @@ static int sde_mdp_get_img(struct sde_fb_data *img, data->srcp_dma_buf = NULL; return ret; } - domain = sde_smmu_get_domain_type(data->flags, rotator); - SDEROT_DBG("%d domain=%d ihndl=%p\n", - __LINE__, domain, data->srcp_dma_buf); - data->srcp_attachment = - sde_smmu_dma_buf_attach(data->srcp_dma_buf, dev, - domain); - if (IS_ERR(data->srcp_attachment)) { - SDEROT_ERR("%d Failed to attach dma buf\n", __LINE__); - ret = PTR_ERR(data->srcp_attachment); - goto err_put; + if (sde_mdp_is_map_needed(data)) { + domain = sde_smmu_get_domain_type(data->flags, rotator); + + SDEROT_DBG("%d domain=%d ihndl=%p\n", + __LINE__, domain, data->srcp_dma_buf); + data->srcp_attachment = + sde_smmu_dma_buf_attach(data->srcp_dma_buf, dev, + domain); + if (IS_ERR(data->srcp_attachment)) { + SDEROT_ERR("%d Failed to attach dma buf\n", __LINE__); + ret = PTR_ERR(data->srcp_attachment); + goto err_put; + } + + SDEROT_DBG("%d attach=%p\n", __LINE__, data->srcp_attachment); + data->srcp_table = + dma_buf_map_attachment(data->srcp_attachment, dir); + if (IS_ERR(data->srcp_table)) { + SDEROT_ERR("%d Failed to map attachment\n", __LINE__); + ret = PTR_ERR(data->srcp_table); + goto err_detach; + } + + SDEROT_DBG("%d table=%p\n", __LINE__, data->srcp_table); + data->addr = 0; + data->len = 0; + data->mapped = false; + data->skip_detach = false; + /* return early, mapping will be done later */ + } else { + struct ion_handle *ihandle = NULL; + struct sg_table *sg_ptr = NULL; + + do { + ihandle = img->handle; + if (IS_ERR_OR_NULL(ihandle)) { + ret = -EINVAL; + SDEROT_ERR("invalid ion handle\n"); + break; + } + + sg_ptr = ion_sg_table(iclient, ihandle); + if (sg_ptr == NULL) { + SDEROT_ERR("ion sg table get failed\n"); + ret = -EINVAL; + break; + } + + if (sg_ptr->nents != 1) { + SDEROT_ERR("ion buffer mapping failed\n"); + ret = -EINVAL; + break; + } + + if (((uint64_t)sg_dma_address(sg_ptr->sgl) >= + PHY_ADDR_4G - sg_ptr->sgl->length)) { + SDEROT_ERR("ion buffer mapped size invalid\n"); + ret = -EINVAL; + break; + } + + data->addr = sg_dma_address(sg_ptr->sgl); + data->len = sg_ptr->sgl->length; + data->mapped = true; + ret = 0; + } while (0); + + if (!IS_ERR_OR_NULL(ihandle)) + ion_free(iclient, ihandle); + return ret; } - SDEROT_DBG("%d attach=%p\n", __LINE__, data->srcp_attachment); - data->srcp_table = - dma_buf_map_attachment(data->srcp_attachment, dir); - if (IS_ERR(data->srcp_table)) { - SDEROT_ERR("%d Failed to map attachment\n", __LINE__); - ret = PTR_ERR(data->srcp_table); - goto err_detach; - } - - SDEROT_DBG("%d table=%p\n", __LINE__, data->srcp_table); - data->addr = 0; - data->len = 0; - data->mapped = false; - data->skip_detach = false; - /* return early, mapping will be done later */ - return 0; err_detach: dma_buf_detach(data->srcp_dma_buf, data->srcp_attachment); @@ -811,23 +864,39 @@ static int sde_mdp_map_buffer(struct sde_mdp_img_data *data, bool rotator, { int ret = -EINVAL; int domain; + struct scatterlist *sg; + unsigned int i; + struct sg_table *table; if (data->addr && data->len) return 0; if (!IS_ERR_OR_NULL(data->srcp_dma_buf)) { - domain = sde_smmu_get_domain_type(data->flags, - rotator); - ret = sde_smmu_map_dma_buf(data->srcp_dma_buf, - data->srcp_table, domain, - &data->addr, &data->len, dir); - if (IS_ERR_VALUE(ret)) { - SDEROT_ERR("smmu map dma buf failed: (%d)\n", ret); - goto err_unmap; + if (sde_mdp_is_map_needed(data)) { + domain = sde_smmu_get_domain_type(data->flags, + rotator); + ret = sde_smmu_map_dma_buf(data->srcp_dma_buf, + data->srcp_table, domain, + &data->addr, &data->len, dir); + if (IS_ERR_VALUE(ret)) { + SDEROT_ERR("smmu map buf failed:(%d)\n", ret); + goto err_unmap; + } + SDEROT_DBG("map %pad/%lx d:%u f:%x\n", + &data->addr, + data->len, + domain, + data->flags); + data->mapped = true; + } else { + data->addr = sg_phys(data->srcp_table->sgl); + data->len = 0; + table = data->srcp_table; + for_each_sg(table->sgl, sg, table->nents, i) { + data->len += sg->length; + } + ret = 0; } - SDEROT_DBG("map %pad/%lx d:%u f:%x\n", &data->addr, data->len, - domain, data->flags); - data->mapped = true; } if (!data->addr) { diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_util.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_util.h index 93074d64bf93..3f94a1570fa2 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_util.h +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_util.h @@ -19,6 +19,7 @@ #include #include #include +#include #include "sde_rotator_hwio.h" #include "sde_rotator_base.h" @@ -44,6 +45,8 @@ #define SDEDEV_ERR(dev, fmt, ...) \ dev_err(dev, " " fmt, ##__VA_ARGS__) +#define PHY_ADDR_4G (1ULL<<32) + struct sde_rect { u16 x; u16 y; @@ -62,12 +65,14 @@ struct sde_rect { #define SDE_SOURCE_ROTATED_90 0x00100000 #define SDE_SECURE_OVERLAY_SESSION 0x00008000 #define SDE_ROT_EXT_DMA_BUF 0x00010000 +#define SDE_SECURE_CAMERA_SESSION 0x00020000 struct sde_rot_data_type; struct sde_fb_data { uint32_t offset; struct dma_buf *buffer; + struct ion_handle *handle; int memory_id; int id; uint32_t flags; @@ -79,6 +84,7 @@ struct sde_layer_plane { /* DMA buffer file descriptor information. */ int fd; struct dma_buf *buffer; + struct ion_handle *handle; /* Pixel offset in the dma buffer. */ uint32_t offset; diff --git a/include/uapi/media/msm_sde_rotator.h b/include/uapi/media/msm_sde_rotator.h index 4487edf0c854..3546b0bf1377 100644 --- a/include/uapi/media/msm_sde_rotator.h +++ b/include/uapi/media/msm_sde_rotator.h @@ -86,4 +86,10 @@ struct msm_sde_rotator_fence { /* SDE Rotator private control ID's */ #define V4L2_CID_SDE_ROTATOR_SECURE (V4L2_CID_USER_BASE + 0x1000) +/* + * This control Id indicates this context is associated with the + * secure camera. + */ +#define V4L2_CID_SDE_ROTATOR_SECURE_CAMERA (V4L2_CID_USER_BASE + 0x2000) + #endif /* __UAPI_MSM_SDE_ROTATOR_H__ */