msm: camera: isp: Add secure mode to isp

Add option to put the isp hardware in secure smmu mode. The
isp stats will still be in non secure mode. Add ioctl to
indicate which buffer queue will be in secure mode so that
they can be mapped in secure mode

CRs-Fixed: 1060631
Change-Id: Ibf2050d0814cc2aaf22a6f510847054d78fd7477
Signed-off-by: Shubhraprakash Das <sadas@codeaurora.org>
This commit is contained in:
Shubhraprakash Das 2016-09-02 01:02:45 -07:00
parent 757c94f42f
commit 97587bf5cb
6 changed files with 157 additions and 37 deletions

View file

@ -188,11 +188,27 @@ static int msm_isp_prepare_v4l2_buf(struct msm_isp_buf_mgr *buf_mgr,
int ret;
struct msm_isp_buffer_mapped_info *mapped_info;
uint32_t accu_length = 0;
struct msm_isp_bufq *bufq = NULL;
bufq = msm_isp_get_bufq(buf_mgr, buf_info->bufq_handle);
if (!bufq) {
pr_err("%s: Invalid bufq, stream id %x\n",
__func__, stream_id);
return -EINVAL;
}
for (i = 0; i < qbuf_buf->num_planes; i++) {
mapped_info = &buf_info->mapped_info[i];
mapped_info->buf_fd = qbuf_buf->planes[i].addr;
ret = cam_smmu_get_phy_addr(buf_mgr->iommu_hdl,
if (bufq->security_mode == SECURE_MODE)
ret = cam_smmu_get_stage2_phy_addr(buf_mgr->iommu_hdl,
mapped_info->buf_fd,
CAM_SMMU_MAP_RW,
buf_mgr->client,
&(mapped_info->paddr),
&(mapped_info->len));
else
ret = cam_smmu_get_phy_addr(buf_mgr->iommu_hdl,
mapped_info->buf_fd,
CAM_SMMU_MAP_RW,
&(mapped_info->paddr),
@ -242,8 +258,13 @@ static void msm_isp_unprepare_v4l2_buf(
for (i = 0; i < buf_info->num_planes; i++) {
mapped_info = &buf_info->mapped_info[i];
cam_smmu_put_phy_addr(buf_mgr->iommu_hdl, mapped_info->buf_fd);
/* SEC_CAM: check any change is needed for secure_mode */
if (bufq->security_mode == SECURE_MODE)
cam_smmu_put_stage2_phy_addr(buf_mgr->iommu_hdl,
mapped_info->buf_fd);
else
cam_smmu_put_phy_addr(buf_mgr->iommu_hdl,
mapped_info->buf_fd);
}
return;
}
@ -259,7 +280,15 @@ static int msm_isp_map_buf(struct msm_isp_buf_mgr *buf_mgr,
__func__, __LINE__, buf_mgr, mapped_info);
return -EINVAL;
}
ret = cam_smmu_get_phy_addr(buf_mgr->iommu_hdl,
if (buf_mgr->secure_enable == SECURE_MODE)
ret = cam_smmu_get_stage2_phy_addr(buf_mgr->iommu_hdl,
fd,
CAM_SMMU_MAP_RW,
buf_mgr->client,
&(mapped_info->paddr),
&(mapped_info->len));
else
ret = cam_smmu_get_phy_addr(buf_mgr->iommu_hdl,
fd,
CAM_SMMU_MAP_RW,
&(mapped_info->paddr),
@ -275,7 +304,11 @@ static int msm_isp_map_buf(struct msm_isp_buf_mgr *buf_mgr,
return rc;
smmu_map_error:
cam_smmu_put_phy_addr(buf_mgr->iommu_hdl,
if (buf_mgr->secure_enable == SECURE_MODE)
cam_smmu_put_stage2_phy_addr(buf_mgr->iommu_hdl,
fd);
else
cam_smmu_put_phy_addr(buf_mgr->iommu_hdl,
fd);
return rc;
}
@ -289,7 +322,12 @@ static int msm_isp_unmap_buf(struct msm_isp_buf_mgr *buf_mgr,
return -EINVAL;
}
cam_smmu_put_phy_addr(buf_mgr->iommu_hdl,
/* SEC_CAMERA: recheck Put part for stats */
if (buf_mgr->secure_enable == SECURE_MODE)
cam_smmu_put_stage2_phy_addr(buf_mgr->iommu_hdl,
fd);
else
cam_smmu_put_phy_addr(buf_mgr->iommu_hdl,
fd);
return 0;
@ -921,7 +959,7 @@ static int msm_isp_get_buf_src(struct msm_isp_buf_mgr *buf_mgr,
}
static int msm_isp_request_bufq(struct msm_isp_buf_mgr *buf_mgr,
struct msm_isp_buf_request *buf_request)
struct msm_isp_buf_request_ver2 *buf_request)
{
int i;
struct msm_isp_bufq *bufq = NULL;
@ -961,6 +999,7 @@ static int msm_isp_request_bufq(struct msm_isp_buf_mgr *buf_mgr,
bufq->num_bufs = buf_request->num_buf;
bufq->buf_type = buf_request->buf_type;
INIT_LIST_HEAD(&bufq->head);
bufq->security_mode = buf_request->security_mode;
for (i = 0; i < buf_request->num_buf; i++) {
bufq->bufs[i].state = MSM_ISP_BUFFER_STATE_INITIALIZED;
@ -1032,15 +1071,25 @@ static int msm_isp_buf_put_scratch(struct msm_isp_buf_mgr *buf_mgr)
if (!buf_mgr->scratch_buf_addr)
return 0;
rc = cam_smmu_put_phy_addr_scratch(buf_mgr->iommu_hdl,
if (buf_mgr->secure_enable == SECURE_MODE) {
rc = cam_smmu_free_stage2_scratch_mem(buf_mgr->iommu_hdl,
buf_mgr->client, buf_mgr->sc_handle);
if (buf_mgr->scratch_buf_stats_addr)
rc = cam_smmu_put_phy_addr_scratch(buf_mgr->iommu_hdl,
buf_mgr->scratch_buf_stats_addr);
} else {
rc = cam_smmu_put_phy_addr_scratch(buf_mgr->iommu_hdl,
buf_mgr->scratch_buf_addr);
}
if (rc)
pr_err("%s: failed to put scratch buffer to img iommu: %d\n",
__func__, rc);
if (!rc)
if (!rc) {
buf_mgr->scratch_buf_addr = 0;
buf_mgr->scratch_buf_stats_addr = 0;
}
return rc;
}
@ -1057,17 +1106,40 @@ static int msm_isp_buf_put_scratch(struct msm_isp_buf_mgr *buf_mgr)
static int msm_isp_buf_get_scratch(struct msm_isp_buf_mgr *buf_mgr)
{
int rc;
size_t range = buf_mgr->scratch_buf_range;
if (buf_mgr->scratch_buf_addr || !buf_mgr->scratch_buf_range)
/* already mapped or not supported */
return 0;
rc = cam_smmu_get_phy_addr_scratch(
if (buf_mgr->secure_enable == SECURE_MODE) {
rc = cam_smmu_alloc_get_stage2_scratch_mem(buf_mgr->iommu_hdl,
CAM_SMMU_MAP_RW,
buf_mgr->client,
&buf_mgr->sc_handle,
&buf_mgr->scratch_buf_addr,
&range);
if (rc)
goto done;
rc = cam_smmu_get_phy_addr_scratch(
buf_mgr->iommu_hdl,
CAM_SMMU_MAP_RW,
&buf_mgr->scratch_buf_stats_addr,
buf_mgr->scratch_buf_range,
SZ_4K);
if (rc)
msm_isp_buf_put_scratch(buf_mgr);
} else {
rc = cam_smmu_get_phy_addr_scratch(
buf_mgr->iommu_hdl,
CAM_SMMU_MAP_RW,
&buf_mgr->scratch_buf_addr,
buf_mgr->scratch_buf_range,
SZ_4K);
buf_mgr->scratch_buf_stats_addr = buf_mgr->scratch_buf_addr;
}
done:
if (rc) {
pr_err("%s: failed to map scratch buffer to img iommu: %d\n",
__func__, rc);
@ -1085,20 +1157,23 @@ int msm_isp_smmu_attach(struct msm_isp_buf_mgr *buf_mgr,
pr_debug("%s: cmd->security_mode : %d\n", __func__, cmd->security_mode);
mutex_lock(&buf_mgr->lock);
if (cmd->iommu_attach_mode == IOMMU_ATTACH) {
buf_mgr->secure_enable = cmd->security_mode;
/*
* Call hypervisor thru scm call to notify secure or
* non-secure mode
*/
if (buf_mgr->attach_ref_cnt == 0) {
rc = cam_smmu_ops(buf_mgr->iommu_hdl,
CAM_SMMU_ATTACH);
if (cmd->security_mode == SECURE_MODE)
rc = cam_smmu_ops(buf_mgr->iommu_hdl,
CAM_SMMU_ATTACH_SEC_VFE_NS_STATS);
else
rc = cam_smmu_ops(buf_mgr->iommu_hdl,
CAM_SMMU_ATTACH);
if (rc < 0) {
pr_err("%s: img smmu attach error, rc :%d\n",
__func__, rc);
goto err1;
goto err1;
}
buf_mgr->secure_enable = cmd->security_mode;
}
buf_mgr->attach_ref_cnt++;
rc = msm_isp_buf_get_scratch(buf_mgr);
@ -1113,8 +1188,12 @@ int msm_isp_smmu_attach(struct msm_isp_buf_mgr *buf_mgr,
if (buf_mgr->attach_ref_cnt == 0) {
rc = msm_isp_buf_put_scratch(buf_mgr);
rc |= cam_smmu_ops(buf_mgr->iommu_hdl,
CAM_SMMU_DETACH);
if (buf_mgr->secure_enable == SECURE_MODE)
rc |= cam_smmu_ops(buf_mgr->iommu_hdl,
CAM_SMMU_DETACH_SEC_VFE_NS_STATS);
else
rc |= cam_smmu_ops(buf_mgr->iommu_hdl,
CAM_SMMU_DETACH);
if (rc < 0) {
pr_err("%s: img/stats smmu detach error, rc :%d\n",
__func__, rc);
@ -1126,8 +1205,11 @@ int msm_isp_smmu_attach(struct msm_isp_buf_mgr *buf_mgr,
return rc;
err2:
if (cam_smmu_ops(buf_mgr->iommu_hdl, CAM_SMMU_DETACH))
pr_err("%s: img smmu detach error\n", __func__);
if (buf_mgr->secure_enable == SECURE_MODE)
cam_smmu_ops(buf_mgr->iommu_hdl,
CAM_SMMU_DETACH_SEC_VFE_NS_STATS);
else
cam_smmu_ops(buf_mgr->iommu_hdl, CAM_SMMU_DETACH);
err1:
mutex_unlock(&buf_mgr->lock);
return rc;
@ -1162,12 +1244,11 @@ static int msm_isp_init_isp_buf_mgr(struct msm_isp_buf_mgr *buf_mgr,
buf_mgr->pagefault_debug_disable = 0;
buf_mgr->frameId_mismatch_recovery = 0;
mutex_unlock(&buf_mgr->lock);
return 0;
/* create ION client */
buf_mgr->client = msm_ion_client_create("vfe");
get_handle_error:
mutex_unlock(&buf_mgr->lock);
return rc;
return 0;
}
static int msm_isp_deinit_isp_buf_mgr(
@ -1186,10 +1267,21 @@ static int msm_isp_deinit_isp_buf_mgr(
buf_mgr->pagefault_debug_disable = 0;
msm_isp_buf_put_scratch(buf_mgr);
cam_smmu_ops(buf_mgr->iommu_hdl, CAM_SMMU_DETACH);
if (buf_mgr->attach_ref_cnt != 0) {
if (buf_mgr->secure_enable == SECURE_MODE)
cam_smmu_ops(buf_mgr->iommu_hdl,
CAM_SMMU_DETACH_SEC_VFE_NS_STATS);
else
cam_smmu_ops(buf_mgr->iommu_hdl, CAM_SMMU_DETACH);
}
cam_smmu_destroy_handle(buf_mgr->iommu_hdl);
buf_mgr->attach_ref_cnt = 0;
buf_mgr->secure_enable = 0;
buf_mgr->attach_ref_cnt = 0;
if (buf_mgr->client) {
ion_client_destroy(buf_mgr->client);
buf_mgr->client = NULL;
}
mutex_unlock(&buf_mgr->lock);
return 0;
}
@ -1200,8 +1292,20 @@ int msm_isp_proc_buf_cmd(struct msm_isp_buf_mgr *buf_mgr,
switch (cmd) {
case VIDIOC_MSM_ISP_REQUEST_BUF: {
struct msm_isp_buf_request *buf_req = arg;
struct msm_isp_buf_request_ver2 buf_req_ver2;
buf_mgr->ops->request_buf(buf_mgr, buf_req);
memcpy(&buf_req_ver2, buf_req,
sizeof(struct msm_isp_buf_request));
buf_req_ver2.security_mode = NON_SECURE_MODE;
buf_mgr->ops->request_buf(buf_mgr, &buf_req_ver2);
memcpy(buf_req, &buf_req_ver2,
sizeof(struct msm_isp_buf_request));
break;
}
case VIDIOC_MSM_ISP_REQUEST_BUF_VER2: {
struct msm_isp_buf_request_ver2 *buf_req_ver2 = arg;
buf_mgr->ops->request_buf(buf_mgr, buf_req_ver2);
break;
}
case VIDIOC_MSM_ISP_ENQUEUE_BUF: {
@ -1393,7 +1497,6 @@ int msm_isp_create_isp_buf_mgr(
buf_mgr->open_count = 0;
buf_mgr->pagefault_debug_disable = 0;
buf_mgr->secure_enable = NON_SECURE_MODE;
buf_mgr->attach_state = MSM_ISP_BUF_MGR_DETACH;
buf_mgr->scratch_buf_range = scratch_buf_range;
mutex_init(&buf_mgr->lock);

View file

@ -119,11 +119,12 @@ struct msm_isp_bufq {
spinlock_t bufq_lock;
/*Native buffer queue*/
struct list_head head;
enum smmu_attach_mode security_mode;
};
struct msm_isp_buf_ops {
int (*request_buf)(struct msm_isp_buf_mgr *buf_mgr,
struct msm_isp_buf_request *buf_request);
struct msm_isp_buf_request_ver2 *buf_request);
int (*enqueue_buf)(struct msm_isp_buf_mgr *buf_mgr,
struct msm_isp_qbuf_info *info);
@ -191,21 +192,20 @@ struct msm_isp_buf_mgr {
struct msm_sd_req_vb2_q *vb2_ops;
/*IOMMU driver*/
int iommu_hdl;
/*Add secure mode*/
int secure_enable;
int num_iommu_ctx;
int num_iommu_secure_ctx;
int attach_ref_cnt;
enum msm_isp_buf_mgr_state attach_state;
struct device *isp_dev;
struct mutex lock;
/* Scratch buffer */
dma_addr_t scratch_buf_addr;
dma_addr_t scratch_buf_stats_addr;
uint32_t scratch_buf_range;
int iommu_hdl;
struct ion_handle *sc_handle;
};
int msm_isp_create_isp_buf_mgr(struct msm_isp_buf_mgr *buf_mgr,

View file

@ -655,8 +655,6 @@ int vfe_hw_probe(struct platform_device *pdev)
goto probe_fail3;
}
msm_isp_enable_debugfs(vfe_dev, msm_isp_bw_request_history);
vfe_dev->buf_mgr->num_iommu_secure_ctx =
vfe_dev->hw_info->num_iommu_secure_ctx;
vfe_dev->buf_mgr->init_done = 1;
vfe_dev->vfe_open_cnt = 0;
return rc;

View file

@ -23,7 +23,7 @@ static inline void msm_isp_stats_cfg_wm_scratch(struct vfe_device *vfe_dev,
{
vfe_dev->hw_info->vfe_ops.stats_ops.update_ping_pong_addr(
vfe_dev, stream_info,
pingpong_status, vfe_dev->buf_mgr->scratch_buf_addr);
pingpong_status, vfe_dev->buf_mgr->scratch_buf_stats_addr);
}
static inline void msm_isp_stats_cfg_stream_scratch(

View file

@ -821,6 +821,7 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd,
break;
}
case VIDIOC_MSM_ISP_REQUEST_BUF:
case VIDIOC_MSM_ISP_REQUEST_BUF_VER2:
/* fallthrough */
case VIDIOC_MSM_ISP_ENQUEUE_BUF:
/* fallthrough */

View file

@ -2,6 +2,7 @@
#define __UAPI_MSMB_ISP__
#include <linux/videodev2.h>
#include <media/msmb_camera.h>
#define MAX_PLANES_PER_STREAM 3
#define MAX_NUM_STREAM 7
@ -556,6 +557,16 @@ struct msm_isp_buf_request {
enum msm_isp_buf_type buf_type;
};
struct msm_isp_buf_request_ver2 {
uint32_t session_id;
uint32_t stream_id;
uint8_t num_buf;
uint32_t handle;
enum msm_isp_buf_type buf_type;
enum smmu_attach_mode security_mode;
uint32_t reserved[4];
};
struct msm_isp_qbuf_plane {
uint32_t addr;
uint32_t offset;
@ -884,8 +895,11 @@ enum msm_isp_ioctl_cmd_code {
MSM_ISP_SET_DUAL_HW_MASTER_SLAVE,
MSM_ISP_MAP_BUF_START_FE,
MSM_ISP_UNMAP_BUF,
MSM_ISP_AHB_CLK_CFG,
MSM_ISP_DUAL_HW_MASTER_SLAVE_SYNC,
MSM_ISP_FETCH_ENG_MULTI_PASS_START,
MSM_ISP_MAP_BUF_START_MULTI_PASS_FE,
MSM_ISP_REQUEST_BUF_VER2,
};
#define VIDIOC_MSM_VFE_REG_CFG \
@ -989,10 +1003,10 @@ enum msm_isp_ioctl_cmd_code {
struct msm_isp_unmap_buf_req)
#define VIDIOC_MSM_ISP_AHB_CLK_CFG \
_IOWR('V', BASE_VIDIOC_PRIVATE+25, struct msm_isp_ahb_clk_cfg)
_IOWR('V', MSM_ISP_AHB_CLK_CFG, struct msm_isp_ahb_clk_cfg)
#define VIDIOC_MSM_ISP_DUAL_HW_MASTER_SLAVE_SYNC \
_IOWR('V', BASE_VIDIOC_PRIVATE+26, \
_IOWR('V', MSM_ISP_DUAL_HW_MASTER_SLAVE_SYNC, \
struct msm_isp_dual_hw_master_slave_sync)
#define VIDIOC_MSM_ISP_FETCH_ENG_MULTI_PASS_START \
@ -1002,4 +1016,8 @@ enum msm_isp_ioctl_cmd_code {
#define VIDIOC_MSM_ISP_MAP_BUF_START_MULTI_PASS_FE \
_IOWR('V', MSM_ISP_MAP_BUF_START_MULTI_PASS_FE, \
struct msm_vfe_fetch_eng_multi_pass_start)
#define VIDIOC_MSM_ISP_REQUEST_BUF_VER2 \
_IOWR('V', MSM_ISP_REQUEST_BUF_VER2, struct msm_isp_buf_request_ver2)
#endif /* __MSMB_ISP__ */