diff options
| -rw-r--r-- | drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c | 147 | ||||
| -rw-r--r-- | drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h | 3 |
2 files changed, 126 insertions, 24 deletions
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c index b9018a226f2f..7e452e9e4ee2 100644 --- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c +++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c @@ -220,6 +220,7 @@ void msm_cpp_deinit_bandwidth_mgr(struct cpp_device *cpp_dev) static int msm_cpp_update_bandwidth_setting(struct cpp_device *cpp_dev, uint64_t ab, uint64_t ib) { int rc; + if (cpp_dev->bus_master_flag) rc = msm_cpp_update_bandwidth(cpp_dev, ab, ib); else @@ -242,6 +243,7 @@ static void msm_enqueue(struct msm_device_queue *queue, struct list_head *entry) { unsigned long flags; + spin_lock_irqsave(&queue->lock, flags); queue->len++; if (queue->len > queue->max) { @@ -302,6 +304,7 @@ static void msm_cpp_timer_queue_update(struct cpp_device *cpp_dev) { uint32_t i; unsigned long flags; + CPP_DBG("Frame done qlen %d\n", cpp_dev->processing_q.len); if (cpp_dev->processing_q.len <= 1) { msm_cpp_clear_timer(cpp_dev); @@ -323,6 +326,7 @@ static void msm_cpp_timer_queue_update(struct cpp_device *cpp_dev) static uint32_t msm_cpp_read(void __iomem *cpp_base) { uint32_t tmp, retry = 0; + do { tmp = msm_camera_io_r(cpp_base + MSM_CPP_MICRO_FIFO_TX_STAT); } while (((tmp & 0x2) == 0x0) && (retry++ < 10)); @@ -409,14 +413,22 @@ static unsigned long msm_cpp_queue_buffer_info(struct cpp_device *cpp_dev, pr_err("error allocating memory\n"); goto error; } - buff->map_info.buff_info = *buffer_info; + buff->map_info.buff_info = *buffer_info; buff->map_info.buf_fd = buffer_info->fd; - rc = cam_smmu_get_phy_addr(cpp_dev->iommu_hdl, buffer_info->fd, - CAM_SMMU_MAP_RW, &buff->map_info.phy_addr, - (size_t *)&buff->map_info.len); + + if (buff_queue->security_mode == SECURE_MODE) + rc = cam_smmu_get_stage2_phy_addr(cpp_dev->iommu_hdl, + buffer_info->fd, CAM_SMMU_MAP_RW, + cpp_dev->ion_client, &buff->map_info.phy_addr, + (size_t *)&buff->map_info.len); + else + rc = cam_smmu_get_phy_addr(cpp_dev->iommu_hdl, + buffer_info->fd, CAM_SMMU_MAP_RW, + &buff->map_info.phy_addr, + (size_t *)&buff->map_info.len); if (rc < 0) { - pr_err("ION mmap failed\n"); + pr_err("ION mmap for CPP buffer failed\n"); kzfree(buff); goto error; } @@ -430,10 +442,17 @@ error: } static void msm_cpp_dequeue_buffer_info(struct cpp_device *cpp_dev, + struct msm_cpp_buff_queue_info_t *buff_queue, struct msm_cpp_buffer_map_list_t *buff) { int ret = -1; - ret = cam_smmu_put_phy_addr(cpp_dev->iommu_hdl, buff->map_info.buf_fd); + + if (buff_queue->security_mode == SECURE_MODE) + ret = cam_smmu_put_stage2_phy_addr(cpp_dev->iommu_hdl, + buff->map_info.buf_fd); + else + ret = cam_smmu_put_phy_addr(cpp_dev->iommu_hdl, + buff->map_info.buf_fd); if (ret < 0) pr_err("Error: cannot put the iommu handle back to ion fd\n"); @@ -466,6 +485,7 @@ static unsigned long msm_cpp_fetch_buffer_info(struct cpp_device *cpp_dev, buffer_info); *fd = buffer_info->fd; } + return phy_addr; } @@ -477,12 +497,12 @@ static int32_t msm_cpp_dequeue_buff_info_list(struct cpp_device *cpp_dev, buff_head = &buff_queue_info->native_buff_head; list_for_each_entry_safe(buff, save, buff_head, entry) { - msm_cpp_dequeue_buffer_info(cpp_dev, buff); + msm_cpp_dequeue_buffer_info(cpp_dev, buff_queue_info, buff); } buff_head = &buff_queue_info->vb2_buff_head; list_for_each_entry_safe(buff, save, buff_head, entry) { - msm_cpp_dequeue_buffer_info(cpp_dev, buff); + msm_cpp_dequeue_buffer_info(cpp_dev, buff_queue_info, buff); } return 0; @@ -502,7 +522,8 @@ static int32_t msm_cpp_dequeue_buff(struct cpp_device *cpp_dev, list_for_each_entry_safe(buff, save, buff_head, entry) { if (buff->map_info.buff_info.index == buff_index) { - msm_cpp_dequeue_buffer_info(cpp_dev, buff); + msm_cpp_dequeue_buffer_info(cpp_dev, buff_queue_info, + buff); break; } } @@ -522,6 +543,8 @@ static int32_t msm_cpp_add_buff_queue_entry(struct cpp_device *cpp_dev, buff_queue_info->used = 1; buff_queue_info->session_id = session_id; buff_queue_info->stream_id = stream_id; + buff_queue_info->security_mode = + cpp_dev->security_mode; INIT_LIST_HEAD(&buff_queue_info->vb2_buff_head); INIT_LIST_HEAD(&buff_queue_info->native_buff_head); return 0; @@ -548,6 +571,7 @@ static int32_t msm_cpp_free_buff_queue_entry(struct cpp_device *cpp_dev, buff_queue_info->used = 0; buff_queue_info->session_id = 0; buff_queue_info->stream_id = 0; + buff_queue_info->security_mode = NON_SECURE_MODE; INIT_LIST_HEAD(&buff_queue_info->vb2_buff_head); INIT_LIST_HEAD(&buff_queue_info->native_buff_head); return 0; @@ -557,6 +581,7 @@ static int32_t msm_cpp_create_buff_queue(struct cpp_device *cpp_dev, uint32_t num_buffq) { struct msm_cpp_buff_queue_info_t *buff_queue; + buff_queue = kzalloc( sizeof(struct msm_cpp_buff_queue_info_t) * num_buffq, GFP_KERNEL); @@ -602,6 +627,7 @@ static int32_t msm_cpp_poll(void __iomem *cpp_base, u32 val) { uint32_t tmp, retry = 0; int32_t rc = 0; + do { tmp = msm_cpp_read(cpp_base); if (tmp != 0xDEADBEEF) @@ -796,6 +822,7 @@ static irqreturn_t msm_cpp_irq(int irq_num, void *data) uint32_t tx_fifo[MSM_CPP_TX_FIFO_LEVEL]; struct cpp_device *cpp_dev = data; struct msm_cpp_tasklet_queue_cmd *queue_cmd; + irq_status = msm_camera_io_r(cpp_dev->base + MSM_CPP_MICRO_IRQGEN_STAT); if (irq_status & 0x8) { @@ -1028,6 +1055,7 @@ reg_enable_failed: static void cpp_release_hardware(struct cpp_device *cpp_dev) { int32_t rc; + if (cpp_dev->state != CPP_STATE_BOOT) { msm_camera_unregister_irq(cpp_dev->pdev, cpp_dev->irq, cpp_dev); tasklet_kill(&cpp_dev->cpp_tasklet); @@ -1061,7 +1089,7 @@ static int32_t cpp_load_fw(struct cpp_device *cpp_dev, char *fw_name_bin) goto end; } pr_debug("%s:%d] FW file: %s\n", __func__, __LINE__, fw_name_bin); - if (NULL == cpp_dev->fw) { + if (cpp_dev->fw == NULL) { pr_err("%s:%d] fw NULL", __func__, __LINE__); rc = -EINVAL; goto end; @@ -1192,7 +1220,8 @@ static int cpp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) int rc; uint32_t i; struct cpp_device *cpp_dev = NULL; - CPP_DBG("E\n"); + + CPP_DBG("E"); if (!sd || !fh) { pr_err("Wrong input parameters sd %pK fh %pK!", @@ -1246,6 +1275,14 @@ static int cpp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) return rc; } cpp_dev->state = CPP_STATE_IDLE; + + CPP_DBG("Invoking msm_ion_client_create()\n"); + cpp_dev->ion_client = msm_ion_client_create("cpp"); + if (cpp_dev->ion_client == NULL) { + pr_err("msm_ion_client_create() failed\n"); + mutex_unlock(&cpp_dev->mutex); + rc = -ENOMEM; + } } mutex_unlock(&cpp_dev->mutex); return 0; @@ -1338,6 +1375,12 @@ static int cpp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) msm_cpp_empty_list(processing_q, list_frame); msm_cpp_empty_list(eventData_q, list_eventdata); cpp_dev->state = CPP_STATE_OFF; + + if (cpp_dev->ion_client) { + CPP_DBG("Invoking ion_client_destroy()\n"); + ion_client_destroy(cpp_dev->ion_client); + cpp_dev->ion_client = NULL; + } } mutex_unlock(&cpp_dev->mutex); @@ -1415,7 +1458,8 @@ static int msm_cpp_notify_frame_done(struct cpp_device *cpp_dev, SWAP_IDENTITY_FOR_BATCH_ON_PREVIEW(processed_frame, iden, processed_frame->duplicate_identity); - memset(&buff_mgr_info, 0 , + + memset(&buff_mgr_info, 0, sizeof(struct msm_buf_mngr_info)); buff_mgr_info.session_id = ((iden >> 16) & 0xFFFF); @@ -1460,7 +1504,7 @@ static int msm_cpp_notify_frame_done(struct cpp_device *cpp_dev, SWAP_IDENTITY_FOR_BATCH_ON_PREVIEW(processed_frame, iden, processed_frame->identity); - memset(&buff_mgr_info, 0 , + memset(&buff_mgr_info, 0, sizeof(struct msm_buf_mngr_info)); buff_mgr_info.session_id = ((iden >> 16) & 0xFFFF); @@ -1500,6 +1544,7 @@ static int msm_cpp_dump_frame_cmd(struct msm_cpp_frame_info_t *frame_info) { int i, i1, i2; struct cpp_device *cpp_dev = cpp_timer.data.cpp_dev; + CPP_DBG("-- start: cpp frame cmd for identity=0x%x, frame_id=%d --\n", frame_info->identity, frame_info->frame_id); @@ -1935,6 +1980,7 @@ static int msm_cpp_check_buf_type(struct msm_buf_mngr_info *buff_mgr_info, { int32_t num_output_bufs = 0; uint32_t i = 0; + if (buff_mgr_info->type == MSM_CAMERA_BUF_MNGR_BUF_USER) { new_frame->batch_info.cont_idx = buff_mgr_info->index; @@ -2009,7 +2055,7 @@ static void msm_cpp_update_frame_msg_phy_address(struct cpp_device *cpp_dev, dup_we_mmu_pf_ptr_off = cpp_dev->payload_params.dup_we_mmu_pf_ptr_off; ref_we_mmu_pf_ptr_off = cpp_dev->payload_params.ref_we_mmu_pf_ptr_off; - pr_debug("%s: feature_mask 0x%x\n", __func__, new_frame->feature_mask); + pr_debug("feature_mask 0x%x\n", new_frame->feature_mask); /* Update individual module status from feature mask */ tnr_enabled = ((new_frame->feature_mask & TNR_MASK) >> 2); @@ -2460,6 +2506,7 @@ static int msm_cpp_cfg_frame(struct cpp_device *cpp_dev, /* get buffer for duplicate output */ if (new_frame->duplicate_output) { int32_t iden = new_frame->duplicate_identity; + CPP_DBG("duplication enabled, dup_id=0x%x", new_frame->duplicate_identity); @@ -2599,7 +2646,7 @@ static int msm_cpp_cfg(struct cpp_device *cpp_dev, int32_t rc = 0; int32_t i = 0; int32_t num_buff = sizeof(k_frame_info.output_buffer_info)/ - sizeof(struct msm_cpp_buffer_info_t); + sizeof(struct msm_cpp_buffer_info_t); if (copy_from_user(&k_frame_info, (void __user *)ioctl_ptr->ioctl_ptr, sizeof(k_frame_info))) @@ -2660,6 +2707,7 @@ static int msm_cpp_copy_from_ioctl_ptr(void *dst_ptr, struct msm_camera_v4l2_ioctl_t *ioctl_ptr) { int ret; + if ((ioctl_ptr->ioctl_ptr == NULL) || (ioctl_ptr->len == 0)) { pr_err("%s: Wrong ioctl_ptr %pK / len %zu\n", __func__, ioctl_ptr, ioctl_ptr->len); @@ -2683,6 +2731,7 @@ static int msm_cpp_copy_from_ioctl_ptr(void *dst_ptr, struct msm_camera_v4l2_ioctl_t *ioctl_ptr) { int ret; + if ((ioctl_ptr->ioctl_ptr == NULL) || (ioctl_ptr->len == 0)) { pr_err("%s: Wrong ioctl_ptr %pK / len %zu\n", __func__, ioctl_ptr, ioctl_ptr->len); @@ -2758,14 +2807,15 @@ static int msm_cpp_validate_input(unsigned int cmd, void *arg, break; default: { if (ioctl_ptr == NULL) { - pr_err("Wrong ioctl_ptr for cmd %u\n", cmd); + pr_err("Wrong ioctl_ptr %pK for cmd %u\n", + ioctl_ptr, cmd); return -EINVAL; } *ioctl_ptr = arg; if ((*ioctl_ptr == NULL) || - (*ioctl_ptr)->ioctl_ptr == NULL) { - pr_err("Error invalid ioctl argument cmd %u", cmd); + ((*ioctl_ptr)->ioctl_ptr == NULL)) { + pr_err("Wrong arg %pK for cmd %u\n", arg, cmd); return -EINVAL; } break; @@ -3007,7 +3057,7 @@ long msm_cpp_subdev_ioctl(struct v4l2_subdev *sd, mutex_unlock(&cpp_dev->mutex); return -EINVAL; } - if (VIDIOC_MSM_CPP_DELETE_STREAM_BUFF == cmd) { + if (cmd == VIDIOC_MSM_CPP_DELETE_STREAM_BUFF) { for (j = 0; j < k_stream_buff_info.num_buffs; j++) { msm_cpp_dequeue_buff(cpp_dev, buff_queue_info, k_stream_buff_info.buffer_info[j].index, @@ -3030,6 +3080,7 @@ STREAM_BUFF_END: case VIDIOC_MSM_CPP_DEQUEUE_STREAM_BUFF_INFO: { uint32_t identity; struct msm_cpp_buff_queue_info_t *buff_queue_info; + CPP_DBG("VIDIOC_MSM_CPP_DEQUEUE_STREAM_BUFF_INFO\n"); if (ioctl_ptr->len != sizeof(uint32_t)) { mutex_unlock(&cpp_dev->mutex); @@ -3078,6 +3129,7 @@ STREAM_BUFF_END: struct msm_device_queue *queue = &cpp_dev->eventData_q; struct msm_queue_cmd *event_qcmd; struct msm_cpp_frame_info_t *process_frame; + CPP_DBG("VIDIOC_MSM_CPP_GET_EVENTPAYLOAD\n"); event_qcmd = msm_dequeue(queue, list_eventdata, POP_FRONT); if (!event_qcmd) { @@ -3106,6 +3158,7 @@ STREAM_BUFF_END: uint32_t msm_cpp_core_clk_idx; struct msm_cpp_clock_settings_t clock_settings; unsigned long clock_rate = 0; + CPP_DBG("VIDIOC_MSM_CPP_SET_CLOCK\n"); if (ioctl_ptr->len == 0) { pr_err("ioctl_ptr->len is 0\n"); @@ -3184,6 +3237,7 @@ STREAM_BUFF_END: break; case VIDIOC_MSM_CPP_QUEUE_BUF: { struct msm_pproc_queue_buf_info queue_buf_info; + CPP_DBG("VIDIOC_MSM_CPP_QUEUE_BUF\n"); if (ioctl_ptr->len != sizeof(struct msm_pproc_queue_buf_info)) { @@ -3266,9 +3320,27 @@ STREAM_BUFF_END: break; case VIDIOC_MSM_CPP_IOMMU_ATTACH: { if (cpp_dev->iommu_state == CPP_IOMMU_STATE_DETACHED) { - rc = cam_smmu_ops(cpp_dev->iommu_hdl, CAM_SMMU_ATTACH); + struct msm_camera_smmu_attach_type cpp_attach_info; + + memset(&cpp_attach_info, 0, sizeof(cpp_attach_info)); + rc = msm_cpp_copy_from_ioctl_ptr(&cpp_attach_info, + ioctl_ptr); if (rc < 0) { - pr_err("%s:%dError iommu_attach_device failed\n", + ERR_COPY_FROM_USER(); + return -EINVAL; + } + + cpp_dev->security_mode = cpp_attach_info.attach; + + if (cpp_dev->security_mode == SECURE_MODE) { + rc = cam_smmu_ops(cpp_dev->iommu_hdl, + CAM_SMMU_ATTACH_SEC_CPP); + } else { + rc = cam_smmu_ops(cpp_dev->iommu_hdl, + CAM_SMMU_ATTACH); + } + if (rc < 0) { + pr_err("%s:%diommu_attach_device failed\n", __func__, __LINE__); rc = -EINVAL; break; @@ -3284,10 +3356,28 @@ STREAM_BUFF_END: case VIDIOC_MSM_CPP_IOMMU_DETACH: { if ((cpp_dev->iommu_state == CPP_IOMMU_STATE_ATTACHED) && (cpp_dev->stream_cnt == 0)) { - rc = cam_smmu_ops(cpp_dev->iommu_hdl, CAM_SMMU_DETACH); + + struct msm_camera_smmu_attach_type cpp_attach_info; + + memset(&cpp_attach_info, 0, sizeof(cpp_attach_info)); + rc = msm_cpp_copy_from_ioctl_ptr(&cpp_attach_info, + ioctl_ptr); if (rc < 0) { - pr_err("%s:%dError iommu atach failed\n", - __func__, __LINE__); + ERR_COPY_FROM_USER(); + return -EINVAL; + } + + cpp_dev->security_mode = cpp_attach_info.attach; + + if (cpp_dev->security_mode == SECURE_MODE) + rc = cam_smmu_ops(cpp_dev->iommu_hdl, + CAM_SMMU_DETACH_SEC_CPP); + else + rc = cam_smmu_ops(cpp_dev->iommu_hdl, + CAM_SMMU_DETACH); + if (rc < 0) { + pr_err("%s:%diommu detach failed\n", __func__, + __LINE__); rc = -EINVAL; break; } @@ -3367,6 +3457,7 @@ static long msm_cpp_subdev_do_ioctl( struct cpp_device *cpp_dev = v4l2_get_subdevdata(sd); struct msm_camera_v4l2_ioctl_t *ioctl_ptr = arg; struct msm_cpp_frame_info_t inst_info; + memset(&inst_info, 0, sizeof(struct msm_cpp_frame_info_t)); for (i = 0; i < MAX_ACTIVE_CPP_INSTANCE; i++) { if (cpp_dev->cpp_subscribe_list[i].vfh == vfh) { @@ -3735,6 +3826,7 @@ static long msm_cpp_subdev_fops_compat_ioctl(struct file *file, struct msm_cpp_frame_info32_t inst_info; struct v4l2_fh *vfh = NULL; uint32_t i; + vfh = file->private_data; memset(&inst_info, 0, sizeof(struct msm_cpp_frame_info32_t)); for (i = 0; i < MAX_ACTIVE_CPP_INSTANCE; i++) { @@ -3978,6 +4070,7 @@ static int msm_cpp_update_gdscr_status(struct cpp_device *cpp_dev, { int rc = 0; int value = 0; + if (!cpp_dev) { pr_err("%s: cpp device invalid\n", __func__); rc = -EINVAL; @@ -4080,6 +4173,7 @@ static int cpp_probe(struct platform_device *pdev) struct cpp_device *cpp_dev; int rc = 0; int i = 0; + CPP_DBG("E"); cpp_dev = kzalloc(sizeof(struct cpp_device), GFP_KERNEL); @@ -4251,6 +4345,8 @@ static int cpp_probe(struct platform_device *pdev) cpp_timer_callback, (unsigned long)&cpp_timer); cpp_dev->fw_name_bin = NULL; cpp_dev->max_timeout_trial_cnt = MSM_CPP_MAX_TIMEOUT_TRIAL; + + if (rc == 0) CPP_DBG("SUCCESS."); else @@ -4293,6 +4389,7 @@ static int cpp_device_remove(struct platform_device *dev) { struct v4l2_subdev *sd = platform_get_drvdata(dev); struct cpp_device *cpp_dev; + if (!sd) { pr_err("%s: Subdevice is NULL\n", __func__); return 0; @@ -4303,6 +4400,7 @@ static int cpp_device_remove(struct platform_device *dev) pr_err("%s: cpp device is NULL\n", __func__); return 0; } + if (cpp_dev->fw) { release_firmware(cpp_dev->fw); cpp_dev->fw = NULL; @@ -4366,6 +4464,7 @@ DEFINE_SIMPLE_ATTRIBUTE(cpp_debugfs_error, NULL, static int msm_cpp_enable_debugfs(struct cpp_device *cpp_dev) { struct dentry *debugfs_base; + debugfs_base = debugfs_create_dir("msm_cpp", NULL); if (!debugfs_base) return -ENOMEM; diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h index d5abe0202717..f46cc10cef46 100644 --- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h +++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h @@ -169,6 +169,7 @@ struct msm_cpp_buff_queue_info_t { uint32_t used; uint16_t session_id; uint16_t stream_id; + enum smmu_attach_mode security_mode; struct list_head vb2_buff_head; struct list_head native_buff_head; }; @@ -234,6 +235,8 @@ struct cpp_device { uint32_t min_clk_rate; int iommu_hdl; + struct ion_client *ion_client; + enum smmu_attach_mode security_mode; /* Reusing proven tasklet from msm isp */ atomic_t irq_cnt; uint8_t taskletq_idx; |
