On 11/25/20 5:13 AM, Alexandre Courbot wrote: > Hi Stan, > > On Fri, Nov 20, 2020 at 9:12 AM Stanimir Varbanov > <stanimir.varbanov@xxxxxxxxxx> wrote: >> >> Init the hfi session only once in queue_setup and also cover that >> with inst->lock. >> >> Signed-off-by: Stanimir Varbanov <stanimir.varbanov@xxxxxxxxxx> >> --- >> drivers/media/platform/qcom/venus/venc.c | 98 ++++++++++++++++++------ >> 1 file changed, 73 insertions(+), 25 deletions(-) >> >> diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c >> index 4ecf78e30b59..3a2e449663d8 100644 >> --- a/drivers/media/platform/qcom/venus/venc.c >> +++ b/drivers/media/platform/qcom/venus/venc.c >> @@ -725,8 +725,10 @@ static int venc_init_session(struct venus_inst *inst) >> int ret; >> >> ret = hfi_session_init(inst, inst->fmt_cap->pixfmt); >> - if (ret) >> - return ret; >> + if (ret == -EINVAL) >> + return 0; > > Why is it safe to ignore EINVAL here? The confusion comes from hfi_session_init() return values. Presently hfi_session_init will return EINVAL when the session is already init. Maybe EINVAL is not fitting well with the expected behavior of the function. I thought about EALREADY, EBUSY but it doesn't fit well to me too. > >> + else if (ret) >> + goto deinit; >> >> ret = venus_helper_set_input_resolution(inst, inst->width, >> inst->height); >> @@ -762,17 +764,13 @@ static int venc_out_num_buffers(struct venus_inst *inst, unsigned int *num) >> struct hfi_buffer_requirements bufreq; >> int ret; >> >> - ret = venc_init_session(inst); >> + ret = venus_helper_get_bufreq(inst, HFI_BUFFER_INPUT, &bufreq); >> if (ret) >> return ret; >> >> - ret = venus_helper_get_bufreq(inst, HFI_BUFFER_INPUT, &bufreq); >> - >> *num = bufreq.count_actual; >> >> - hfi_session_deinit(inst); >> - >> - return ret; >> + return 0; >> } >> >> static int venc_queue_setup(struct vb2_queue *q, >> @@ -781,7 +779,7 @@ static int venc_queue_setup(struct vb2_queue *q, >> { >> struct venus_inst *inst = vb2_get_drv_priv(q); >> unsigned int num, min = 4; >> - int ret = 0; >> + int ret; >> >> if (*num_planes) { >> if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && >> @@ -803,6 +801,17 @@ static int venc_queue_setup(struct vb2_queue *q, >> return 0; >> } >> >> + ret = mutex_lock_interruptible(&inst->lock); I'll keep original mutex_lock here in next version. >> + if (ret) >> + return ret; >> + >> + ret = venc_init_session(inst); >> + >> + mutex_unlock(&inst->lock); >> + >> + if (ret) >> + return ret; >> + >> switch (q->type) { >> case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: >> *num_planes = inst->fmt_out->num_planes; >> @@ -838,6 +847,54 @@ static int venc_queue_setup(struct vb2_queue *q, >> return ret; >> } >> >> +static int venc_buf_init(struct vb2_buffer *vb) >> +{ >> + struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue); >> + >> + inst->buf_count++; >> + >> + return venus_helper_vb2_buf_init(vb); >> +} >> + >> +static void venc_release_session(struct venus_inst *inst) >> +{ >> + int ret, abort = 0; >> + >> + mutex_lock(&inst->lock); >> + >> + ret = hfi_session_deinit(inst); >> + abort = (ret && ret != -EINVAL) ? 1 : 0; > > Here as well, I think a comment is warranted to explain why we can > ignore EINVAL. OK, will update that. > >> + >> + if (inst->session_error) >> + abort = 1; >> + >> + if (abort) >> + hfi_session_abort(inst); >> + >> + mutex_unlock(&inst->lock); >> + >> + venus_pm_load_scale(inst); >> + INIT_LIST_HEAD(&inst->registeredbufs); >> + venus_pm_release_core(inst); >> +} >> + >> +static void venc_buf_cleanup(struct vb2_buffer *vb) >> +{ >> + struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue); >> + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); >> + struct venus_buffer *buf = to_venus_buffer(vbuf); >> + >> + mutex_lock(&inst->lock); >> + if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) >> + if (!list_empty(&inst->registeredbufs)) >> + list_del_init(&buf->reg_list); >> + mutex_unlock(&inst->lock); >> + >> + inst->buf_count--; >> + if (!inst->buf_count) >> + venc_release_session(inst); > > We are calling venc_init_session() during the queue setup but > venc_release_session() when the last buffer is cleaned up. For > symmetry, wouldn't it make sense to call venc_init_session() when the > first buffer is initialized by venc_buf_init()? Otherwise we can No, the session must be initialized in queue_setup in order to return the number and sizes of source/destination buffers. I raised several times the need of symmetrical operation to queue_setup to cover reqbuf(0) but there is no progress on that. Latest suggestion was to use .vidioc_reqbufs ioctl op but I fall with some other issues and at the end I came to this counting buf_init|cleanup solution. > potentially have a scenario where the queue is set up, but no buffer > is ever created, leading to the session never being released. dmabuf import case? <cut> -- regards, Stan