@@ -102,6 +102,8 @@ struct venus_core {
struct device *dev_dec;
struct device *dev_enc;
struct mutex lock;
+ struct mutex dec_lock;
+ struct mutex enc_lock;
struct list_head instances;
atomic_t insts_count;
unsigned int state;
@@ -243,7 +245,7 @@ struct venus_buffer {
*/
struct venus_inst {
struct list_head list;
- struct mutex lock;
+ struct mutex *lock;
struct venus_core *core;
struct list_head internalbufs;
struct list_head registeredbufs;
@@ -512,7 +512,7 @@ static void delayed_process_buf_func(struct work_struct *work)
inst = container_of(work, struct venus_inst, delayed_process_work);
- mutex_lock(&inst->lock);
+ mutex_lock(inst->lock);
if (!(inst->streamon_out & inst->streamon_cap))
goto unlock;
@@ -528,7 +528,7 @@ static void delayed_process_buf_func(struct work_struct *work)
list_del_init(&buf->ref_list);
}
unlock:
- mutex_unlock(&inst->lock);
+ mutex_unlock(inst->lock);
}
void venus_helper_release_buf_ref(struct venus_inst *inst, unsigned int idx)
@@ -621,7 +621,7 @@ void venus_helper_vb2_buf_queue(struct vb2_buffer *vb)
struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
int ret;
- mutex_lock(&inst->lock);
+ mutex_lock(inst->lock);
v4l2_m2m_buf_queue(m2m_ctx, vbuf);
@@ -637,7 +637,7 @@ void venus_helper_vb2_buf_queue(struct vb2_buffer *vb)
return_buf_error(inst, vbuf);
unlock:
- mutex_unlock(&inst->lock);
+ mutex_unlock(inst->lock);
}
EXPORT_SYMBOL_GPL(venus_helper_vb2_buf_queue);
@@ -659,7 +659,7 @@ void venus_helper_vb2_stop_streaming(struct vb2_queue *q)
struct venus_core *core = inst->core;
int ret;
- mutex_lock(&inst->lock);
+ mutex_lock(inst->lock);
if (inst->streamon_out & inst->streamon_cap) {
ret = hfi_session_stop(inst);
@@ -685,7 +685,7 @@ void venus_helper_vb2_stop_streaming(struct vb2_queue *q)
else
inst->streamon_cap = 0;
- mutex_unlock(&inst->lock);
+ mutex_unlock(inst->lock);
}
EXPORT_SYMBOL_GPL(venus_helper_vb2_stop_streaming);
@@ -731,7 +731,7 @@ void venus_helper_m2m_device_run(void *priv)
struct v4l2_m2m_buffer *buf, *n;
int ret;
- mutex_lock(&inst->lock);
+ mutex_lock(inst->lock);
v4l2_m2m_for_each_dst_buf_safe(m2m_ctx, buf, n) {
ret = session_process_buf(inst, &buf->vb);
@@ -745,7 +745,7 @@ void venus_helper_m2m_device_run(void *priv)
return_buf_error(inst, &buf->vb);
}
- mutex_unlock(&inst->lock);
+ mutex_unlock(inst->lock);
}
EXPORT_SYMBOL_GPL(venus_helper_m2m_device_run);
@@ -493,14 +493,12 @@ vdec_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd)
if (ret)
return ret;
- mutex_lock(&inst->lock);
-
/*
* Implement V4L2_DEC_CMD_STOP by enqueue an empty buffer on decoder
* input to signal EOS.
*/
if (!(inst->streamon_out & inst->streamon_cap))
- goto unlock;
+ return 0;
fdata.buffer_type = HFI_BUFFER_INPUT;
fdata.flags |= HFI_BUFFERFLAG_EOS;
@@ -508,8 +506,6 @@ vdec_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd)
ret = hfi_session_process_buf(inst, &fdata);
-unlock:
- mutex_unlock(&inst->lock);
return ret;
}
@@ -720,17 +716,13 @@ static int vdec_start_streaming(struct vb2_queue *q, unsigned int count)
u32 ptype;
int ret;
- mutex_lock(&inst->lock);
-
if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
inst->streamon_out = 1;
else
inst->streamon_cap = 1;
- if (!(inst->streamon_out & inst->streamon_cap)) {
- mutex_unlock(&inst->lock);
+ if (!(inst->streamon_out & inst->streamon_cap))
return 0;
- }
venus_helper_init_instance(inst);
@@ -771,8 +763,6 @@ static int vdec_start_streaming(struct vb2_queue *q, unsigned int count)
if (ret)
goto deinit_sess;
- mutex_unlock(&inst->lock);
-
return 0;
deinit_sess:
@@ -783,7 +773,6 @@ static int vdec_start_streaming(struct vb2_queue *q, unsigned int count)
inst->streamon_out = 0;
else
inst->streamon_cap = 0;
- mutex_unlock(&inst->lock);
return ret;
}
@@ -794,6 +783,8 @@ static const struct vb2_ops vdec_vb2_ops = {
.start_streaming = vdec_start_streaming,
.stop_streaming = venus_helper_vb2_stop_streaming,
.buf_queue = venus_helper_vb2_buf_queue,
+ .wait_prepare = vb2_ops_wait_prepare,
+ .wait_finish = vb2_ops_wait_finish,
};
static void vdec_buf_done(struct venus_inst *inst, unsigned int buf_type,
@@ -940,6 +931,7 @@ static int m2m_queue_init(void *priv, struct vb2_queue *src_vq,
src_vq->allow_zero_bytesused = 1;
src_vq->min_buffers_needed = 1;
src_vq->dev = inst->core->dev;
+ src_vq->lock = &inst->core->dec_lock;
ret = vb2_queue_init(src_vq);
if (ret)
return ret;
@@ -954,6 +946,7 @@ static int m2m_queue_init(void *priv, struct vb2_queue *src_vq,
dst_vq->allow_zero_bytesused = 1;
dst_vq->min_buffers_needed = 1;
dst_vq->dev = inst->core->dev;
+ dst_vq->lock = &inst->core->dec_lock;
ret = vb2_queue_init(dst_vq);
if (ret) {
vb2_queue_release(src_vq);
@@ -976,9 +969,9 @@ static int vdec_open(struct file *file)
INIT_LIST_HEAD(&inst->registeredbufs);
INIT_LIST_HEAD(&inst->internalbufs);
INIT_LIST_HEAD(&inst->list);
- mutex_init(&inst->lock);
inst->core = core;
+ inst->lock = &core->dec_lock;
inst->session_type = VIDC_SESSION_TYPE_DEC;
inst->num_output_bufs = 1;
@@ -1044,7 +1037,6 @@ static int vdec_close(struct file *file)
v4l2_m2m_release(inst->m2m_dev);
vdec_ctrl_deinit(inst);
hfi_session_destroy(inst);
- mutex_destroy(&inst->lock);
v4l2_fh_del(&inst->fh);
v4l2_fh_exit(&inst->fh);
@@ -1092,12 +1084,14 @@ static int vdec_probe(struct platform_device *pdev)
if (!vdev)
return -ENOMEM;
+ mutex_init(&core->dec_lock);
strlcpy(vdev->name, "qcom-venus-decoder", sizeof(vdev->name));
vdev->release = video_device_release;
vdev->fops = &vdec_fops;
vdev->ioctl_ops = &vdec_ioctl_ops;
vdev->vfl_dir = VFL_DIR_M2M;
vdev->v4l2_dev = &core->v4l2_dev;
+ vdev->lock = &core->dec_lock;
vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
@@ -1123,6 +1117,7 @@ static int vdec_remove(struct platform_device *pdev)
video_unregister_device(core->vdev_dec);
pm_runtime_disable(core->dev_dec);
+ mutex_destroy(&core->dec_lock);
return 0;
}
@@ -922,17 +922,13 @@ static int venc_start_streaming(struct vb2_queue *q, unsigned int count)
struct venus_inst *inst = vb2_get_drv_priv(q);
int ret;
- mutex_lock(&inst->lock);
-
if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
inst->streamon_out = 1;
else
inst->streamon_cap = 1;
- if (!(inst->streamon_out & inst->streamon_cap)) {
- mutex_unlock(&inst->lock);
+ if (!(inst->streamon_out & inst->streamon_cap))
return 0;
- }
venus_helper_init_instance(inst);
@@ -960,8 +956,6 @@ static int venc_start_streaming(struct vb2_queue *q, unsigned int count)
if (ret)
goto deinit_sess;
- mutex_unlock(&inst->lock);
-
return 0;
deinit_sess:
@@ -972,7 +966,6 @@ static int venc_start_streaming(struct vb2_queue *q, unsigned int count)
inst->streamon_out = 0;
else
inst->streamon_cap = 0;
- mutex_unlock(&inst->lock);
return ret;
}
@@ -983,6 +976,8 @@ static const struct vb2_ops venc_vb2_ops = {
.start_streaming = venc_start_streaming,
.stop_streaming = venus_helper_vb2_stop_streaming,
.buf_queue = venus_helper_vb2_buf_queue,
+ .wait_prepare = vb2_ops_wait_prepare,
+ .wait_finish = vb2_ops_wait_finish,
};
static void venc_buf_done(struct venus_inst *inst, unsigned int buf_type,
@@ -1054,6 +1049,7 @@ static int m2m_queue_init(void *priv, struct vb2_queue *src_vq,
src_vq->allow_zero_bytesused = 1;
src_vq->min_buffers_needed = 1;
src_vq->dev = inst->core->dev;
+ src_vq->lock = &inst->core->enc_lock;
if (inst->core->res->hfi_version == HFI_VERSION_1XX)
src_vq->bidirectional = 1;
ret = vb2_queue_init(src_vq);
@@ -1070,6 +1066,7 @@ static int m2m_queue_init(void *priv, struct vb2_queue *src_vq,
dst_vq->allow_zero_bytesused = 1;
dst_vq->min_buffers_needed = 1;
dst_vq->dev = inst->core->dev;
+ dst_vq->lock = &inst->core->enc_lock;
ret = vb2_queue_init(dst_vq);
if (ret) {
vb2_queue_release(src_vq);
@@ -1121,9 +1118,9 @@ static int venc_open(struct file *file)
INIT_LIST_HEAD(&inst->registeredbufs);
INIT_LIST_HEAD(&inst->internalbufs);
INIT_LIST_HEAD(&inst->list);
- mutex_init(&inst->lock);
inst->core = core;
+ inst->lock = &core->enc_lock;
inst->session_type = VIDC_SESSION_TYPE_ENC;
venus_helper_init_instance(inst);
@@ -1188,7 +1185,6 @@ static int venc_close(struct file *file)
v4l2_m2m_release(inst->m2m_dev);
venc_ctrl_deinit(inst);
hfi_session_destroy(inst);
- mutex_destroy(&inst->lock);
v4l2_fh_del(&inst->fh);
v4l2_fh_exit(&inst->fh);
@@ -1237,11 +1233,13 @@ static int venc_probe(struct platform_device *pdev)
return -ENOMEM;
strlcpy(vdev->name, "qcom-venus-encoder", sizeof(vdev->name));
+ mutex_init(&core->enc_lock);
vdev->release = video_device_release;
vdev->fops = &venc_fops;
vdev->ioctl_ops = &venc_ioctl_ops;
vdev->vfl_dir = VFL_DIR_M2M;
vdev->v4l2_dev = &core->v4l2_dev;
+ vdev->lock = &core->enc_lock;
vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
@@ -1267,6 +1265,7 @@ static int venc_remove(struct platform_device *pdev)
video_unregister_device(core->vdev_enc);
pm_runtime_disable(core->dev_enc);
+ mutex_destroy(&core->enc_lock);
return 0;
}
video_device and vb2_queue locks are now both mandatory. Add them, remove driver ad-hoc locking, and implement wait_{prepare, finish}. To stay on the safe side, this commit uses a single mutex for both locks. Better latency can be obtained by separating these if needed. Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com> --- drivers/media/platform/qcom/venus/core.h | 4 +++- drivers/media/platform/qcom/venus/helpers.c | 16 ++++++++-------- drivers/media/platform/qcom/venus/vdec.c | 25 ++++++++++--------------- drivers/media/platform/qcom/venus/venc.c | 19 +++++++++---------- 4 files changed, 30 insertions(+), 34 deletions(-)