Skip to content

Commit 3227a8f

Browse files
Stanimir Varbanovmchehab
authored andcommitted
media: venus: Handle fatal errors during encoding and decoding
According to stateful decoder docs a fatal failure of decoding (and encoding) could be recover it by closing the corresponding file handle and open new one or reinitialize decoding (and encoding) by stop streaming on both queues. In order to satisfy this requirement we add a mechanism ins sys_error_handler and corresponding decoder and encoder drivers to wait for sys_error_done waitqueue in reqbuf. Signed-off-by: Stanimir Varbanov <[email protected]> Tested-by: Vikash Garodia <[email protected]> Signed-off-by: Mauro Carvalho Chehab <[email protected]>
1 parent aa6dcf1 commit 3227a8f

File tree

5 files changed

+40
-3
lines changed

5 files changed

+40
-3
lines changed

drivers/media/platform/qcom/venus/core.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,16 +95,17 @@ static void venus_sys_error_handler(struct work_struct *work)
9595
failed = true;
9696
}
9797

98-
hfi_core_deinit(core, true);
99-
100-
mutex_lock(&core->lock);
98+
core->ops->core_deinit(core);
99+
core->state = CORE_UNINIT;
101100

102101
for (i = 0; i < max_attempts; i++) {
103102
if (!pm_runtime_active(core->dev_dec) && !pm_runtime_active(core->dev_enc))
104103
break;
105104
msleep(10);
106105
}
107106

107+
mutex_lock(&core->lock);
108+
108109
venus_shutdown(core);
109110

110111
venus_coredump(core);
@@ -162,6 +163,7 @@ static void venus_sys_error_handler(struct work_struct *work)
162163

163164
mutex_lock(&core->lock);
164165
clear_bit(0, &core->sys_error);
166+
wake_up_all(&core->sys_err_done);
165167
mutex_unlock(&core->lock);
166168
}
167169

@@ -316,6 +318,7 @@ static int venus_probe(struct platform_device *pdev)
316318
INIT_LIST_HEAD(&core->instances);
317319
mutex_init(&core->lock);
318320
INIT_DELAYED_WORK(&core->work, venus_sys_error_handler);
321+
init_waitqueue_head(&core->sys_err_done);
319322

320323
ret = devm_request_threaded_irq(dev, core->irq, hfi_isr, hfi_isr_thread,
321324
IRQF_TRIGGER_HIGH | IRQF_ONESHOT,

drivers/media/platform/qcom/venus/core.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ struct venus_core {
184184
struct completion done;
185185
unsigned int error;
186186
unsigned long sys_error;
187+
wait_queue_head_t sys_err_done;
187188
const struct hfi_core_ops *core_ops;
188189
const struct venus_pm_ops *pm_ops;
189190
struct mutex pm_lock;
@@ -336,6 +337,7 @@ enum venus_inst_modes {
336337
* @registeredbufs: a list of registered capture bufferes
337338
* @delayed_process: a list of delayed buffers
338339
* @delayed_process_work: a work_struct for process delayed buffers
340+
* @nonblock: nonblocking flag
339341
* @ctrl_handler: v4l control handler
340342
* @controls: a union of decoder and encoder control parameters
341343
* @fh: a holder of v4l file handle structure
@@ -399,6 +401,7 @@ struct venus_inst {
399401
struct list_head registeredbufs;
400402
struct list_head delayed_process;
401403
struct work_struct delayed_process_work;
404+
bool nonblock;
402405

403406
struct v4l2_ctrl_handler ctrl_handler;
404407
union {

drivers/media/platform/qcom/venus/helpers.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1510,6 +1510,8 @@ void venus_helper_vb2_stop_streaming(struct vb2_queue *q)
15101510

15111511
venus_pm_release_core(inst);
15121512

1513+
inst->session_error = 0;
1514+
15131515
mutex_unlock(&inst->lock);
15141516
}
15151517
EXPORT_SYMBOL_GPL(venus_helper_vb2_stop_streaming);

drivers/media/platform/qcom/venus/vdec.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,7 @@ static int vdec_queue_setup(struct vb2_queue *q,
846846
unsigned int sizes[], struct device *alloc_devs[])
847847
{
848848
struct venus_inst *inst = vb2_get_drv_priv(q);
849+
struct venus_core *core = inst->core;
849850
unsigned int in_num, out_num;
850851
int ret = 0;
851852

@@ -871,6 +872,16 @@ static int vdec_queue_setup(struct vb2_queue *q,
871872
return 0;
872873
}
873874

875+
if (test_bit(0, &core->sys_error)) {
876+
if (inst->nonblock)
877+
return -EAGAIN;
878+
879+
ret = wait_event_interruptible(core->sys_err_done,
880+
!test_bit(0, &core->sys_error));
881+
if (ret)
882+
return ret;
883+
}
884+
874885
ret = vdec_pm_get(inst);
875886
if (ret)
876887
return ret;
@@ -1198,6 +1209,8 @@ static void vdec_stop_streaming(struct vb2_queue *q)
11981209

11991210
venus_helper_buffers_done(inst, q->type, VB2_BUF_STATE_ERROR);
12001211

1212+
inst->session_error = 0;
1213+
12011214
if (ret)
12021215
goto unlock;
12031216

@@ -1473,6 +1486,7 @@ static void vdec_event_notify(struct venus_inst *inst, u32 event,
14731486
switch (event) {
14741487
case EVT_SESSION_ERROR:
14751488
inst->session_error = true;
1489+
venus_helper_vb2_queue_error(inst);
14761490
dev_err(dev, "dec: event session error %x\n", inst->error);
14771491
break;
14781492
case EVT_SYS_EVENT_CHANGE:
@@ -1594,6 +1608,8 @@ static int vdec_open(struct file *file)
15941608
inst->bit_depth = VIDC_BITDEPTH_8;
15951609
inst->pic_struct = HFI_INTERLACE_FRAME_PROGRESSIVE;
15961610
init_waitqueue_head(&inst->reconf_wait);
1611+
inst->nonblock = file->f_flags & O_NONBLOCK;
1612+
15971613
venus_helper_init_instance(inst);
15981614

15991615
ret = vdec_ctrl_init(inst);

drivers/media/platform/qcom/venus/venc.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -966,6 +966,7 @@ static int venc_queue_setup(struct vb2_queue *q,
966966
unsigned int sizes[], struct device *alloc_devs[])
967967
{
968968
struct venus_inst *inst = vb2_get_drv_priv(q);
969+
struct venus_core *core = inst->core;
969970
unsigned int num, min = 4;
970971
int ret;
971972

@@ -989,6 +990,16 @@ static int venc_queue_setup(struct vb2_queue *q,
989990
return 0;
990991
}
991992

993+
if (test_bit(0, &core->sys_error)) {
994+
if (inst->nonblock)
995+
return -EAGAIN;
996+
997+
ret = wait_event_interruptible(core->sys_err_done,
998+
!test_bit(0, &core->sys_error));
999+
if (ret)
1000+
return ret;
1001+
}
1002+
9921003
ret = venc_pm_get(inst);
9931004
if (ret)
9941005
return ret;
@@ -1248,6 +1259,7 @@ static void venc_event_notify(struct venus_inst *inst, u32 event,
12481259

12491260
if (event == EVT_SESSION_ERROR) {
12501261
inst->session_error = true;
1262+
venus_helper_vb2_queue_error(inst);
12511263
dev_err(dev, "enc: event session error %x\n", inst->error);
12521264
}
12531265
}
@@ -1331,6 +1343,7 @@ static int venc_open(struct file *file)
13311343
inst->session_type = VIDC_SESSION_TYPE_ENC;
13321344
inst->clk_data.core_id = VIDC_CORE_ID_DEFAULT;
13331345
inst->core_acquired = false;
1346+
inst->nonblock = file->f_flags & O_NONBLOCK;
13341347

13351348
venus_helper_init_instance(inst);
13361349

0 commit comments

Comments
 (0)