diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/platform/qcom/venus/core.c | 9 | ||||
-rw-r--r-- | drivers/media/platform/qcom/venus/core.h | 3 | ||||
-rw-r--r-- | drivers/media/platform/qcom/venus/helpers.c | 2 | ||||
-rw-r--r-- | drivers/media/platform/qcom/venus/vdec.c | 16 | ||||
-rw-r--r-- | drivers/media/platform/qcom/venus/venc.c | 13 |
5 files changed, 40 insertions, 3 deletions
diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c index 0f31cc5668c1..3916af160ea9 100644 --- a/drivers/media/platform/qcom/venus/core.c +++ b/drivers/media/platform/qcom/venus/core.c @@ -95,9 +95,8 @@ static void venus_sys_error_handler(struct work_struct *work) failed = true; } - hfi_core_deinit(core, true); - - mutex_lock(&core->lock); + core->ops->core_deinit(core); + core->state = CORE_UNINIT; for (i = 0; i < max_attempts; i++) { if (!pm_runtime_active(core->dev_dec) && !pm_runtime_active(core->dev_enc)) @@ -105,6 +104,8 @@ static void venus_sys_error_handler(struct work_struct *work) msleep(10); } + mutex_lock(&core->lock); + venus_shutdown(core); venus_coredump(core); @@ -162,6 +163,7 @@ static void venus_sys_error_handler(struct work_struct *work) mutex_lock(&core->lock); clear_bit(0, &core->sys_error); + wake_up_all(&core->sys_err_done); mutex_unlock(&core->lock); } @@ -316,6 +318,7 @@ static int venus_probe(struct platform_device *pdev) INIT_LIST_HEAD(&core->instances); mutex_init(&core->lock); INIT_DELAYED_WORK(&core->work, venus_sys_error_handler); + init_waitqueue_head(&core->sys_err_done); ret = devm_request_threaded_irq(dev, core->irq, hfi_isr, hfi_isr_thread, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index 46d87a1226ff..262e021fd19e 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -184,6 +184,7 @@ struct venus_core { struct completion done; unsigned int error; unsigned long sys_error; + wait_queue_head_t sys_err_done; const struct hfi_core_ops *core_ops; const struct venus_pm_ops *pm_ops; struct mutex pm_lock; @@ -336,6 +337,7 @@ enum venus_inst_modes { * @registeredbufs: a list of registered capture bufferes * @delayed_process: a list of delayed buffers * @delayed_process_work: a work_struct for process delayed buffers + * @nonblock: nonblocking flag * @ctrl_handler: v4l control handler * @controls: a union of decoder and encoder control parameters * @fh: a holder of v4l file handle structure @@ -399,6 +401,7 @@ struct venus_inst { struct list_head registeredbufs; struct list_head delayed_process; struct work_struct delayed_process_work; + bool nonblock; struct v4l2_ctrl_handler ctrl_handler; union { diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index dacd244d5aca..caf47ca6a950 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -1510,6 +1510,8 @@ void venus_helper_vb2_stop_streaming(struct vb2_queue *q) venus_pm_release_core(inst); + inst->session_error = 0; + mutex_unlock(&inst->lock); } EXPORT_SYMBOL_GPL(venus_helper_vb2_stop_streaming); diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index 11990a95d346..36e783eeafe9 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -846,6 +846,7 @@ static int vdec_queue_setup(struct vb2_queue *q, unsigned int sizes[], struct device *alloc_devs[]) { struct venus_inst *inst = vb2_get_drv_priv(q); + struct venus_core *core = inst->core; unsigned int in_num, out_num; int ret = 0; @@ -871,6 +872,16 @@ static int vdec_queue_setup(struct vb2_queue *q, return 0; } + if (test_bit(0, &core->sys_error)) { + if (inst->nonblock) + return -EAGAIN; + + ret = wait_event_interruptible(core->sys_err_done, + !test_bit(0, &core->sys_error)); + if (ret) + return ret; + } + ret = vdec_pm_get(inst); if (ret) return ret; @@ -1198,6 +1209,8 @@ static void vdec_stop_streaming(struct vb2_queue *q) venus_helper_buffers_done(inst, q->type, VB2_BUF_STATE_ERROR); + inst->session_error = 0; + if (ret) goto unlock; @@ -1473,6 +1486,7 @@ static void vdec_event_notify(struct venus_inst *inst, u32 event, switch (event) { case EVT_SESSION_ERROR: inst->session_error = true; + venus_helper_vb2_queue_error(inst); dev_err(dev, "dec: event session error %x\n", inst->error); break; case EVT_SYS_EVENT_CHANGE: @@ -1594,6 +1608,8 @@ static int vdec_open(struct file *file) inst->bit_depth = VIDC_BITDEPTH_8; inst->pic_struct = HFI_INTERLACE_FRAME_PROGRESSIVE; init_waitqueue_head(&inst->reconf_wait); + inst->nonblock = file->f_flags & O_NONBLOCK; + venus_helper_init_instance(inst); ret = vdec_ctrl_init(inst); diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c index 472f2cff4573..84bafc3118cc 100644 --- a/drivers/media/platform/qcom/venus/venc.c +++ b/drivers/media/platform/qcom/venus/venc.c @@ -966,6 +966,7 @@ static int venc_queue_setup(struct vb2_queue *q, unsigned int sizes[], struct device *alloc_devs[]) { struct venus_inst *inst = vb2_get_drv_priv(q); + struct venus_core *core = inst->core; unsigned int num, min = 4; int ret; @@ -989,6 +990,16 @@ static int venc_queue_setup(struct vb2_queue *q, return 0; } + if (test_bit(0, &core->sys_error)) { + if (inst->nonblock) + return -EAGAIN; + + ret = wait_event_interruptible(core->sys_err_done, + !test_bit(0, &core->sys_error)); + if (ret) + return ret; + } + ret = venc_pm_get(inst); if (ret) return ret; @@ -1248,6 +1259,7 @@ static void venc_event_notify(struct venus_inst *inst, u32 event, if (event == EVT_SESSION_ERROR) { inst->session_error = true; + venus_helper_vb2_queue_error(inst); dev_err(dev, "enc: event session error %x\n", inst->error); } } @@ -1331,6 +1343,7 @@ static int venc_open(struct file *file) inst->session_type = VIDC_SESSION_TYPE_ENC; inst->clk_data.core_id = VIDC_CORE_ID_DEFAULT; inst->core_acquired = false; + inst->nonblock = file->f_flags & O_NONBLOCK; venus_helper_init_instance(inst); |