diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp.c index 6ad23be7d8e..33974b0c149 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.c @@ -115,7 +115,8 @@ static int __devinit vfe_probe(struct platform_device *pdev) vfe_dev->subdev.sd.flags |= V4L2_SUBDEV_FL_HAS_EVENTS; v4l2_set_subdevdata(&vfe_dev->subdev.sd, vfe_dev); platform_set_drvdata(pdev, &vfe_dev->subdev.sd); - mutex_init(&vfe_dev->mutex); + mutex_init(&vfe_dev->realtime_mutex); + mutex_init(&vfe_dev->core_mutex); spin_lock_init(&vfe_dev->tasklet_lock); spin_lock_init(&vfe_dev->shared_data_lock); media_entity_init(&vfe_dev->subdev.sd.entity, 0, NULL, 0); diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h index cfbe29c0ec3..ad8aa82e426 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h @@ -369,7 +369,8 @@ struct vfe_device { struct completion reset_complete; struct completion halt_complete; struct completion stream_config_complete; - struct mutex mutex; + struct mutex realtime_mutex; + struct mutex core_mutex; atomic_t irq_cnt; uint8_t taskletq_idx; diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c index ae8950065f8..3035d93a563 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c @@ -120,55 +120,82 @@ long msm_isp_ioctl(struct v4l2_subdev *sd, long rc = 0; struct vfe_device *vfe_dev = v4l2_get_subdevdata(sd); - mutex_lock(&vfe_dev->mutex); - ISP_DBG("%s cmd: %d\n", __func__, cmd); + /* Use real time mutex for hard real-time ioctls such as + * buffer operations and register updates. + * Use core mutex for other ioctls that could take + * longer time to complete such as start/stop ISP streams + * which blocks until the hardware start/stop streaming + */ + ISP_DBG("%s cmd: %d\n", __func__, _IOC_TYPE(cmd)); switch (cmd) { case VIDIOC_MSM_VFE_REG_CFG: { + mutex_lock(&vfe_dev->realtime_mutex); rc = msm_isp_proc_cmd(vfe_dev, arg); + mutex_unlock(&vfe_dev->realtime_mutex); break; } case VIDIOC_MSM_ISP_REQUEST_BUF: case VIDIOC_MSM_ISP_ENQUEUE_BUF: case VIDIOC_MSM_ISP_RELEASE_BUF: { + mutex_lock(&vfe_dev->realtime_mutex); rc = msm_isp_proc_buf_cmd(vfe_dev->buf_mgr, cmd, arg); + mutex_unlock(&vfe_dev->realtime_mutex); break; } case VIDIOC_MSM_ISP_REQUEST_STREAM: + mutex_lock(&vfe_dev->core_mutex); rc = msm_isp_request_axi_stream(vfe_dev, arg); + mutex_unlock(&vfe_dev->core_mutex); break; case VIDIOC_MSM_ISP_RELEASE_STREAM: + mutex_lock(&vfe_dev->core_mutex); rc = msm_isp_release_axi_stream(vfe_dev, arg); + mutex_unlock(&vfe_dev->core_mutex); break; case VIDIOC_MSM_ISP_CFG_STREAM: + mutex_lock(&vfe_dev->core_mutex); rc = msm_isp_cfg_axi_stream(vfe_dev, arg); + mutex_unlock(&vfe_dev->core_mutex); break; case VIDIOC_MSM_ISP_INPUT_CFG: + mutex_lock(&vfe_dev->core_mutex); rc = msm_isp_cfg_input(vfe_dev, arg); + mutex_unlock(&vfe_dev->core_mutex); break; case VIDIOC_MSM_ISP_SET_SRC_STATE: + mutex_lock(&vfe_dev->core_mutex); msm_isp_set_src_state(vfe_dev, arg); + mutex_unlock(&vfe_dev->core_mutex); break; case VIDIOC_MSM_ISP_REQUEST_STATS_STREAM: + mutex_lock(&vfe_dev->core_mutex); rc = msm_isp_request_stats_stream(vfe_dev, arg); + mutex_unlock(&vfe_dev->core_mutex); break; case VIDIOC_MSM_ISP_RELEASE_STATS_STREAM: + mutex_lock(&vfe_dev->core_mutex); rc = msm_isp_release_stats_stream(vfe_dev, arg); + mutex_unlock(&vfe_dev->core_mutex); break; case VIDIOC_MSM_ISP_CFG_STATS_STREAM: + mutex_lock(&vfe_dev->core_mutex); rc = msm_isp_cfg_stats_stream(vfe_dev, arg); + mutex_unlock(&vfe_dev->core_mutex); break; case VIDIOC_MSM_ISP_CFG_STATS_COMP_POLICY: + mutex_lock(&vfe_dev->core_mutex); rc = msm_isp_cfg_stats_comp_policy(vfe_dev, arg); + mutex_unlock(&vfe_dev->core_mutex); break; case VIDIOC_MSM_ISP_UPDATE_STREAM: + mutex_lock(&vfe_dev->core_mutex); rc = msm_isp_update_axi_stream(vfe_dev, arg); + mutex_unlock(&vfe_dev->core_mutex); break; default: pr_err("%s: Invalid ISP command\n", __func__); rc = -EINVAL; } - - mutex_unlock(&vfe_dev->mutex); return rc; } @@ -623,23 +650,27 @@ int msm_isp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) long rc; ISP_DBG("%s\n", __func__); - mutex_lock(&vfe_dev->mutex); + mutex_lock(&vfe_dev->realtime_mutex); + mutex_lock(&vfe_dev->core_mutex); if (vfe_dev->vfe_open_cnt == 1) { pr_err("VFE already open\n"); - mutex_unlock(&vfe_dev->mutex); + mutex_unlock(&vfe_dev->core_mutex); + mutex_unlock(&vfe_dev->realtime_mutex); return -ENODEV; } if (vfe_dev->hw_info->vfe_ops.core_ops.init_hw(vfe_dev) < 0) { pr_err("%s: init hardware failed\n", __func__); - mutex_unlock(&vfe_dev->mutex); + mutex_unlock(&vfe_dev->core_mutex); + mutex_unlock(&vfe_dev->realtime_mutex); return -EBUSY; } rc = vfe_dev->hw_info->vfe_ops.core_ops.reset_hw(vfe_dev); if (rc <= 0) { pr_err("%s: reset timeout\n", __func__); - mutex_unlock(&vfe_dev->mutex); + mutex_unlock(&vfe_dev->core_mutex); + mutex_unlock(&vfe_dev->realtime_mutex); return -EINVAL; } vfe_dev->vfe_hw_version = msm_camera_io_r(vfe_dev->vfe_base); @@ -659,7 +690,8 @@ int msm_isp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) vfe_dev->axi_data.hw_info = vfe_dev->hw_info->axi_hw_info; vfe_dev->vfe_open_cnt++; vfe_dev->taskletq_idx = 0; - mutex_unlock(&vfe_dev->mutex); + mutex_unlock(&vfe_dev->core_mutex); + mutex_unlock(&vfe_dev->realtime_mutex); return 0; } @@ -669,10 +701,12 @@ int msm_isp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) long rc; struct vfe_device *vfe_dev = v4l2_get_subdevdata(sd); ISP_DBG("%s\n", __func__); - mutex_lock(&vfe_dev->mutex); + mutex_lock(&vfe_dev->realtime_mutex); + mutex_lock(&vfe_dev->core_mutex); if (vfe_dev->vfe_open_cnt == 0) { pr_err("%s: Invalid close\n", __func__); - mutex_unlock(&vfe_dev->mutex); + mutex_unlock(&vfe_dev->core_mutex); + mutex_unlock(&vfe_dev->realtime_mutex); return -ENODEV; } @@ -689,6 +723,7 @@ int msm_isp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) vfe_dev->hw_info->vfe_ops.core_ops.release_hw(vfe_dev); vfe_dev->vfe_open_cnt--; - mutex_unlock(&vfe_dev->mutex); + mutex_unlock(&vfe_dev->core_mutex); + mutex_unlock(&vfe_dev->realtime_mutex); return 0; }