media: venus: venc: Init the session only once in queue_setup
authorStanimir Varbanov <stanimir.varbanov@linaro.org>
Fri, 4 Dec 2020 10:01:36 +0000 (11:01 +0100)
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>
Wed, 13 Jan 2021 08:05:36 +0000 (09:05 +0100)
Init the hfi session only once in queue_setup and also cover that
with inst->lock.

Tested-by: Fritz Koenig <frkoenig@chromium.org>
Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
drivers/media/platform/qcom/venus/venc.c

index 248bae1..700c045 100644 (file)
@@ -725,7 +725,9 @@ static int venc_init_session(struct venus_inst *inst)
        int ret;
 
        ret = hfi_session_init(inst, inst->fmt_cap->pixfmt);
-       if (ret)
+       if (ret == -EINVAL)
+               return 0;
+       else if (ret)
                return ret;
 
        ret = venus_helper_set_input_resolution(inst, inst->width,
@@ -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,13 @@ static int venc_queue_setup(struct vb2_queue *q,
                return 0;
        }
 
+       mutex_lock(&inst->lock);
+       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 +843,49 @@ 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;
+
+       mutex_lock(&inst->lock);
+
+       ret = hfi_session_deinit(inst);
+       if (ret || inst->session_error)
+               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);
+}
+
 static int venc_verify_conf(struct venus_inst *inst)
 {
        enum hfi_version ver = inst->core->res->hfi_version;
@@ -888,38 +936,32 @@ static int venc_start_streaming(struct vb2_queue *q, unsigned int count)
        inst->sequence_cap = 0;
        inst->sequence_out = 0;
 
-       ret = venc_init_session(inst);
-       if (ret)
-               goto bufs_done;
-
        ret = venus_pm_acquire_core(inst);
        if (ret)
-               goto deinit_sess;
+               goto error;
 
        ret = venc_set_properties(inst);
        if (ret)
-               goto deinit_sess;
+               goto error;
 
        ret = venc_verify_conf(inst);
        if (ret)
-               goto deinit_sess;
+               goto error;
 
        ret = venus_helper_set_num_bufs(inst, inst->num_input_bufs,
                                        inst->num_output_bufs, 0);
        if (ret)
-               goto deinit_sess;
+               goto error;
 
        ret = venus_helper_vb2_start_streaming(inst);
        if (ret)
-               goto deinit_sess;
+               goto error;
 
        mutex_unlock(&inst->lock);
 
        return 0;
 
-deinit_sess:
-       hfi_session_deinit(inst);
-bufs_done:
+error:
        venus_helper_buffers_done(inst, q->type, VB2_BUF_STATE_QUEUED);
        if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
                inst->streamon_out = 0;
@@ -940,7 +982,8 @@ static void venc_vb2_buf_queue(struct vb2_buffer *vb)
 
 static const struct vb2_ops venc_vb2_ops = {
        .queue_setup = venc_queue_setup,
-       .buf_init = venus_helper_vb2_buf_init,
+       .buf_init = venc_buf_init,
+       .buf_cleanup = venc_buf_cleanup,
        .buf_prepare = venus_helper_vb2_buf_prepare,
        .start_streaming = venc_start_streaming,
        .stop_streaming = venus_helper_vb2_stop_streaming,