diff options
author | Hu Kejun <william.hu@rock-chips.com> | 2018-12-21 10:27:17 +0800 |
---|---|---|
committer | Tao Huang <huangtao@rock-chips.com> | 2019-01-24 14:28:44 +0800 |
commit | f944fd08f6c5c5116538faec997583b9e59b8f21 (patch) | |
tree | 35478ebcf48baebecd0c2d38a44e553e2ab01672 | |
parent | 60edcb0765113a21387de88e0df6b97984dfa0d9 (diff) |
media: rk-isp10: add api mutex for multi-thread app
Change-Id: If2f8600a5f6cdf57bc3859b81a68539bb2d05a84
Signed-off-by: Hu Kejun <william.hu@rock-chips.com>
-rw-r--r-- | drivers/media/platform/rk-isp10/cif_isp10.h | 2 | ||||
-rw-r--r-- | drivers/media/platform/rk-isp10/cif_isp10_v4l2.c | 90 |
2 files changed, 85 insertions, 7 deletions
diff --git a/drivers/media/platform/rk-isp10/cif_isp10.h b/drivers/media/platform/rk-isp10/cif_isp10.h index eb570430f2ae..c24d4e4323dd 100644 --- a/drivers/media/platform/rk-isp10/cif_isp10.h +++ b/drivers/media/platform/rk-isp10/cif_isp10.h @@ -674,6 +674,8 @@ struct cif_isp10_device { struct pltfrm_soc_cfg soc_cfg; void *nodes; + struct mutex api_mutex; /* user api mutex */ + }; struct cif_isp10_fmt *get_cif_isp10_output_format(int index); diff --git a/drivers/media/platform/rk-isp10/cif_isp10_v4l2.c b/drivers/media/platform/rk-isp10/cif_isp10_v4l2.c index b19efe054892..480f5caaee50 100644 --- a/drivers/media/platform/rk-isp10/cif_isp10_v4l2.c +++ b/drivers/media/platform/rk-isp10/cif_isp10_v4l2.c @@ -550,6 +550,7 @@ static int cif_isp10_v4l2_streamon( static u32 streamon_cnt_dma; u32 stream_ids = to_stream_id(file); + mutex_lock(&dev->api_mutex); cif_isp10_pltfrm_pr_dbg(dev->dev, "%s(%d)\n", cif_isp10_v4l2_buf_type_string(queue->type), (stream_ids & CIF_ISP10_STREAM_MP) ? ++streamon_cnt_mp : @@ -568,10 +569,12 @@ static int cif_isp10_v4l2_streamon( goto err; } + mutex_unlock(&dev->api_mutex); return 0; err: (void)vb2_queue_release(queue); cif_isp10_pltfrm_pr_err(dev->dev, "failed with error %d\n", ret); + mutex_unlock(&dev->api_mutex); return ret; } @@ -609,12 +612,17 @@ static int cif_isp10_v4l2_streamoff( void *priv, enum v4l2_buf_type buf_type) { - int ret = cif_isp10_v4l2_do_streamoff(file); + int ret; + struct vb2_queue *queue = to_vb2_queue(file); + struct cif_isp10_device *dev = to_cif_isp10_device(queue); + mutex_lock(&dev->api_mutex); + ret = cif_isp10_v4l2_do_streamoff(file); if (IS_ERR_VALUE(ret)) cif_isp10_pltfrm_pr_err(NULL, "failed with error %d\n", ret); + mutex_unlock(&dev->api_mutex); return ret; } @@ -660,12 +668,14 @@ static int cif_isp10_v4l2_reqbufs( struct cif_isp10_device *dev = to_cif_isp10_device(queue); enum cif_isp10_stream_id strm = to_cif_isp10_stream_id(queue); + mutex_lock(&dev->api_mutex); ret = vb2_ioctl_reqbufs(file, priv, req); if (IS_ERR_VALUE(ret)) { cif_isp10_pltfrm_pr_err(NULL, "videobuf_reqbufs failed with error %d\n", ret); } cif_isp10_reqbufs(dev, strm, req); + mutex_unlock(&dev->api_mutex); return ret; } @@ -675,11 +685,15 @@ static int cif_isp10_v4l2_querybuf( struct v4l2_buffer *buf) { int ret; + struct vb2_queue *queue = to_vb2_queue(file); + struct cif_isp10_device *dev = to_cif_isp10_device(queue); + mutex_lock(&dev->api_mutex); ret = vb2_ioctl_querybuf(file, priv, buf); if (IS_ERR_VALUE(ret)) cif_isp10_pltfrm_pr_err(NULL, "videobuf_querybuf failed with error %d\n", ret); + mutex_unlock(&dev->api_mutex); return ret; } @@ -694,10 +708,12 @@ static int cif_isp10_v4l2_s_ctrl( enum cif_isp10_cid id = cif_isp10_v4l2_cid2cif_isp10_cid(vc->id); int val = vc->value; + int ret; if (IS_ERR_VALUE(id)) return id; + mutex_lock(&dev->api_mutex); switch (vc->id) { case V4L2_CID_COLORFX: val = cif_isp10_v4l2_colorfx2cif_isp10_ie(val); @@ -716,7 +732,9 @@ static int cif_isp10_v4l2_s_ctrl( break; } - return cif_isp10_s_ctrl(dev, id, val); + ret = cif_isp10_s_ctrl(dev, id, val); + mutex_unlock(&dev->api_mutex); + return ret; } static int cif_isp10_v4l2_s_fmt( @@ -735,8 +753,11 @@ static int cif_isp10_v4l2_s_fmt( "%s\n", cif_isp10_v4l2_buf_type_string(queue->type)); - if (node->owner && node->owner != fh) + mutex_lock(&dev->api_mutex); + if (node->owner && node->owner != fh) { + mutex_unlock(&dev->api_mutex); return -EBUSY; + } strm_fmt.frm_fmt.pix_fmt = cif_isp10_v4l2_pix_fmt2cif_isp10_pix_fmt( @@ -759,10 +780,12 @@ static int cif_isp10_v4l2_s_fmt( if (IS_ERR_VALUE(ret)) goto err; + mutex_unlock(&dev->api_mutex); return 0; err: cif_isp10_pltfrm_pr_err(NULL, "failed with error %d\n", ret); + mutex_unlock(&dev->api_mutex); return ret; } @@ -777,6 +800,7 @@ static int cif_isp10_v4l2_g_fmt( struct cif_isp10_device *dev = to_cif_isp10_device(queue); enum cif_isp10_stream_id stream_id = to_cif_isp10_stream_id(queue); + mutex_lock(&dev->api_mutex); switch (stream_id) { case CIF_ISP10_STREAM_SP: pix_fmt = dev->config.mi_config.sp.output.pix_fmt; @@ -795,9 +819,11 @@ static int cif_isp10_v4l2_g_fmt( f->fmt.pix.pixelformat = cif_isp10_pix_fmt2v4l2_pix_fmt(pix_fmt, queue); break; default: + mutex_unlock(&dev->api_mutex); return -EINVAL; } + mutex_unlock(&dev->api_mutex); return 0; } @@ -810,14 +836,17 @@ static int cif_isp10_v4l2_g_input( struct vb2_queue *queue = to_vb2_queue(file); struct cif_isp10_device *dev = to_cif_isp10_device(queue); + mutex_lock(&dev->api_mutex); ret = cif_isp10_g_input(dev, i); if (IS_ERR_VALUE(ret)) goto err; + mutex_unlock(&dev->api_mutex); return 0; err: cif_isp10_pltfrm_pr_err(NULL, "failed with error %d\n", ret); + mutex_unlock(&dev->api_mutex); return ret; } @@ -832,14 +861,17 @@ static int cif_isp10_v4l2_s_input( cif_isp10_pltfrm_pr_dbg(dev->dev, "setting input to %d\n", i); + mutex_lock(&dev->api_mutex); ret = cif_isp10_s_input(dev, i); if (IS_ERR_VALUE(ret)) goto err; + mutex_unlock(&dev->api_mutex); return 0; err: cif_isp10_pltfrm_pr_err(NULL, "failed with error %d\n", ret); + mutex_unlock(&dev->api_mutex); return ret; } @@ -854,6 +886,7 @@ static int cif_isp10_v4l2_enum_framesizes( struct cif_isp10_device *dev = to_cif_isp10_device(queue); struct v4l2_subdev_frame_size_enum fse; + mutex_lock(&dev->api_mutex); if (IS_ERR_OR_NULL(dev->img_src)) { cif_isp10_pltfrm_pr_err(NULL, "input has not yet been selected, cannot enumerate formats\n"); @@ -873,8 +906,11 @@ static int cif_isp10_v4l2_enum_framesizes( fsize->discrete.width = fse.max_width; fsize->discrete.height = fse.max_height; + mutex_unlock(&dev->api_mutex); return 0; + err: + mutex_unlock(&dev->api_mutex); return ret; } @@ -1032,6 +1068,7 @@ static int cif_isp10_v4l2_open( "video device video%d.%d (%s)\n", vdev->num, vdev->minor, vdev->name); + mutex_lock(&dev->api_mutex); if (vdev->minor == cif_isp10_v4l2_dev->node[SP_DEV].vdev.minor) { buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; stream_id = CIF_ISP10_STREAM_SP; @@ -1064,8 +1101,10 @@ static int cif_isp10_v4l2_open( v4l2_fh_add(&fh->fh); node = to_node(fh); - if (++node->users > 1) + if (++node->users > 1) { + mutex_unlock(&dev->api_mutex); return 0; + } /* First open of the device, so initialize everything */ node->owner = NULL; @@ -1083,10 +1122,12 @@ static int cif_isp10_v4l2_open( goto err; } + mutex_unlock(&dev->api_mutex); return 0; err: cif_isp10_pltfrm_pr_err(NULL, "failed with error %d\n", ret); + mutex_unlock(&dev->api_mutex); return ret; } @@ -1102,11 +1143,13 @@ static int cif_isp10_v4l2_release(struct file *file) cif_isp10_pltfrm_pr_dbg(dev->dev, "%s\n", cif_isp10_v4l2_buf_type_string(queue->type)); + mutex_lock(&dev->api_mutex); if (node->users) { --node->users; } else { cif_isp10_pltfrm_pr_warn(dev->dev, "number of users for this device is already 0\n"); + mutex_unlock(&dev->api_mutex); return 0; } @@ -1125,6 +1168,9 @@ static int cif_isp10_v4l2_release(struct file *file) if (node->owner == fh) node->owner = NULL; + if (file->private_data == queue->owner) + queue->owner = NULL; + v4l2_fh_del(&fh->fh); v4l2_fh_exit(&fh->fh); kfree(fh); @@ -1132,6 +1178,8 @@ static int cif_isp10_v4l2_release(struct file *file) if (IS_ERR_VALUE(ret)) cif_isp10_pltfrm_pr_err(dev->dev, "failed with error %d\n", ret); + + mutex_unlock(&dev->api_mutex); return ret; } @@ -1360,10 +1408,12 @@ static long v4l2_default_ioctl(struct file *file, void *fh, struct vb2_queue *queue = to_vb2_queue(file); struct cif_isp10_device *dev = to_cif_isp10_device(queue); + mutex_lock(&dev->api_mutex); if (!arg) { cif_isp10_pltfrm_pr_err(dev->dev, "NULL Pointer Violation from IOCTL arg:0x%lx\n", (unsigned long)arg); + mutex_unlock(&dev->api_mutex); return ret; } @@ -1377,6 +1427,7 @@ static long v4l2_default_ioctl(struct file *file, void *fh, if (ret < 0) { cif_isp10_pltfrm_pr_err(dev->dev, "failed to get sensor mode data\n"); + mutex_unlock(&dev->api_mutex); return ret; } @@ -1403,6 +1454,7 @@ static long v4l2_default_ioctl(struct file *file, void *fh, if (IS_ERR_VALUE(ret)) { cif_isp10_pltfrm_pr_err(dev->dev, "failed to get isp_output data\n"); + mutex_unlock(&dev->api_mutex); return ret; } } @@ -1416,6 +1468,7 @@ static long v4l2_default_ioctl(struct file *file, void *fh, if (ret < 0) { cif_isp10_pltfrm_pr_err(dev->dev, "failed to get camera module information\n"); + mutex_unlock(&dev->api_mutex); return ret; } } else if (cmd == RK_VIDIOC_SENSOR_CONFIGINFO) { @@ -1428,6 +1481,7 @@ static long v4l2_default_ioctl(struct file *file, void *fh, if (ret < 0) { cif_isp10_pltfrm_pr_err(dev->dev, "failed to get camera module information\n"); + mutex_unlock(&dev->api_mutex); return ret; } } else if (cmd == RK_VIDIOC_SENSOR_REG_ACCESS) { @@ -1440,10 +1494,12 @@ static long v4l2_default_ioctl(struct file *file, void *fh, if (ret < 0) { cif_isp10_pltfrm_pr_err(dev->dev, "failed to get camera module information\n"); + mutex_unlock(&dev->api_mutex); return ret; } } + mutex_unlock(&dev->api_mutex); return ret; } @@ -1470,21 +1526,26 @@ static int v4l2_enum_input(struct file *file, void *priv, struct cif_isp10_device *dev = to_cif_isp10_device(queue); const char *inp_name; + mutex_lock(&dev->api_mutex); if ((queue->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && (queue->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)) { cif_isp10_pltfrm_pr_err(NULL, "wrong buffer queue %d\n", queue->type); + mutex_unlock(&dev->api_mutex); return -EINVAL; } inp_name = cif_isp10_g_input_name(dev, input->index); - if (IS_ERR_OR_NULL(inp_name)) + if (IS_ERR_OR_NULL(inp_name)) { + mutex_unlock(&dev->api_mutex); return -EINVAL; + } input->type = V4L2_INPUT_TYPE_CAMERA; input->std = V4L2_STD_UNKNOWN; strncpy(input->name, inp_name, sizeof(input->name)-1); + mutex_unlock(&dev->api_mutex); return 0; } @@ -1560,11 +1621,15 @@ static int v4l2_enum_fmt_cap(struct file *file, void *fh, { int ret = 0; int xgold_num_format = 0; + struct vb2_queue *queue = to_vb2_queue(file); + struct cif_isp10_device *dev = to_cif_isp10_device(queue); + mutex_lock(&dev->api_mutex); xgold_num_format = get_cif_isp10_output_format_desc_size(); if ((f->index >= xgold_num_format) || (get_cif_isp10_output_format_desc(f->index)->pixelformat == 0)) { cif_isp10_pltfrm_pr_err(NULL, "index %d\n", f->index); + mutex_unlock(&dev->api_mutex); return -EINVAL; } strlcpy(f->description, @@ -1574,6 +1639,8 @@ static int v4l2_enum_fmt_cap(struct file *file, void *fh, get_cif_isp10_output_format_desc(f->index)->pixelformat; f->flags = get_cif_isp10_output_format_desc(f->index)->flags; + mutex_unlock(&dev->api_mutex); + return ret; } @@ -1584,7 +1651,9 @@ static int v4l2_g_ctrl(struct file *file, void *priv, struct cif_isp10_device *dev = to_cif_isp10_device(queue); enum cif_isp10_cid id = cif_isp10_v4l2_cid2cif_isp10_cid(vc->id); + int ret; + mutex_lock(&dev->api_mutex); if (id == CIF_ISP10_CID_MIN_BUFFER_FOR_CAPTURE) { /* Three buffers needed at least. * one for MI_MP_Y_BASE_AD_INIT, one for MI_MP_Y_BASE_AD_SHD @@ -1594,11 +1663,13 @@ static int v4l2_g_ctrl(struct file *file, void *priv, cif_isp10_pltfrm_pr_dbg(dev->dev, "V4L2_CID_MIN_BUFFERS_FOR_CAPTURE %d\n", vc->value); + mutex_unlock(&dev->api_mutex); return 0; } - return cif_isp10_img_src_g_ctrl(dev->img_src, - id, &vc->value); + ret = cif_isp10_img_src_g_ctrl(dev->img_src, id, &vc->value); + mutex_unlock(&dev->api_mutex); + return ret; } static int v4l2_s_ext_ctrls(struct file *file, void *priv, @@ -1662,6 +1733,7 @@ int cif_isp10_v4l2_cropcap( u32 target_width, target_height; u32 h_offs, v_offs; + mutex_lock(&dev->api_mutex); if ((dev->config.input_sel == CIF_ISP10_INP_DMA) || (dev->config.input_sel == CIF_ISP10_INP_DMA_IE)) { /* calculate cropping for aspect ratio */ @@ -1675,6 +1747,7 @@ int cif_isp10_v4l2_cropcap( if (ret < 0) { cif_isp10_pltfrm_pr_err(dev->dev, "failed to get target frame size\n"); + mutex_unlock(&dev->api_mutex); return ret; } @@ -1711,6 +1784,7 @@ int cif_isp10_v4l2_cropcap( if (ret < 0) { cif_isp10_pltfrm_pr_err(dev->dev, "failed to get target frame size\n"); + mutex_unlock(&dev->api_mutex); return ret; } @@ -1743,6 +1817,7 @@ int cif_isp10_v4l2_cropcap( a->bounds.left, a->bounds.top); + mutex_unlock(&dev->api_mutex); return ret; } @@ -1910,6 +1985,7 @@ static int cif_isp10_v4l2_drv_probe(struct platform_device *pdev) spin_lock_init(&dev->iowrite32_verify_lock); spin_lock_init(&dev->isp_state_lock); init_waitqueue_head(&dev->isp_stop_wait); + mutex_init(&dev->api_mutex); ret = v4l2_device_register(dev->dev, &dev->v4l2_dev); if (IS_ERR_VALUE(ret)) { |