summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/media/platform/qcom/venus/core.c9
-rw-r--r--drivers/media/platform/qcom/venus/core.h3
-rw-r--r--drivers/media/platform/qcom/venus/helpers.c2
-rw-r--r--drivers/media/platform/qcom/venus/vdec.c16
-rw-r--r--drivers/media/platform/qcom/venus/venc.c13
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);