Skip to content

Commit 40d87aa

Browse files
Mansur Alisha Shaikmchehab
authored andcommitted
media: venus: vdec: decoded picture buffer handling during reconfig sequence
In existing implementation, driver is freeing and un-mapping all the decoded picture buffers(DPB) as part of dynamic resolution change(DRC) handling. As a result, when firmware try to access the DPB buffer, from previous sequence, SMMU context fault is seen due to the buffer being already unmapped. With this change, driver defines ownership of each DPB buffer. If a buffer is owned by firmware, driver would skip from un-mapping the same. Signed-off-by: Mansur Alisha Shaik <[email protected]> Signed-off-by: Stanimir Varbanov <[email protected]> Signed-off-by: Mauro Carvalho Chehab <[email protected]>
1 parent 3227a8f commit 40d87aa

File tree

4 files changed

+60
-2
lines changed

4 files changed

+60
-2
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,7 @@ struct venus_inst {
458458
bool next_buf_last;
459459
bool drain_active;
460460
enum venus_inst_modes flags;
461+
struct ida dpb_ids;
461462
};
462463

463464
#define IS_V1(core) ((core)->res->hfi_version == HFI_VERSION_1XX)

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

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
44
* Copyright (C) 2017 Linaro Ltd.
55
*/
6+
#include <linux/idr.h>
67
#include <linux/list.h>
78
#include <linux/mutex.h>
89
#include <linux/slab.h>
@@ -21,13 +22,20 @@
2122
#define NUM_MBS_720P (((ALIGN(1280, 16)) >> 4) * ((ALIGN(736, 16)) >> 4))
2223
#define NUM_MBS_4K (((ALIGN(4096, 16)) >> 4) * ((ALIGN(2304, 16)) >> 4))
2324

25+
enum dpb_buf_owner {
26+
DRIVER,
27+
FIRMWARE,
28+
};
29+
2430
struct intbuf {
2531
struct list_head list;
2632
u32 type;
2733
size_t size;
2834
void *va;
2935
dma_addr_t da;
3036
unsigned long attrs;
37+
enum dpb_buf_owner owned_by;
38+
u32 dpb_out_tag;
3139
};
3240

3341
bool venus_helper_check_codec(struct venus_inst *inst, u32 v4l2_pixfmt)
@@ -95,9 +103,16 @@ int venus_helper_queue_dpb_bufs(struct venus_inst *inst)
95103
fdata.device_addr = buf->da;
96104
fdata.buffer_type = buf->type;
97105

106+
if (buf->owned_by == FIRMWARE)
107+
continue;
108+
109+
fdata.clnt_data = buf->dpb_out_tag;
110+
98111
ret = hfi_session_process_buf(inst, &fdata);
99112
if (ret)
100113
goto fail;
114+
115+
buf->owned_by = FIRMWARE;
101116
}
102117

103118
fail:
@@ -110,13 +125,19 @@ int venus_helper_free_dpb_bufs(struct venus_inst *inst)
110125
struct intbuf *buf, *n;
111126

112127
list_for_each_entry_safe(buf, n, &inst->dpbbufs, list) {
128+
if (buf->owned_by == FIRMWARE)
129+
continue;
130+
131+
ida_free(&inst->dpb_ids, buf->dpb_out_tag);
132+
113133
list_del_init(&buf->list);
114134
dma_free_attrs(inst->core->dev, buf->size, buf->va, buf->da,
115135
buf->attrs);
116136
kfree(buf);
117137
}
118138

119-
INIT_LIST_HEAD(&inst->dpbbufs);
139+
if (list_empty(&inst->dpbbufs))
140+
INIT_LIST_HEAD(&inst->dpbbufs);
120141

121142
return 0;
122143
}
@@ -134,6 +155,7 @@ int venus_helper_alloc_dpb_bufs(struct venus_inst *inst)
134155
unsigned int i;
135156
u32 count;
136157
int ret;
158+
int id;
137159

138160
/* no need to allocate dpb buffers */
139161
if (!inst->dpb_fmt)
@@ -171,6 +193,15 @@ int venus_helper_alloc_dpb_bufs(struct venus_inst *inst)
171193
ret = -ENOMEM;
172194
goto fail;
173195
}
196+
buf->owned_by = DRIVER;
197+
198+
id = ida_alloc_min(&inst->dpb_ids, VB2_MAX_FRAME, GFP_KERNEL);
199+
if (id < 0) {
200+
ret = id;
201+
goto fail;
202+
}
203+
204+
buf->dpb_out_tag = id;
174205

175206
list_add_tail(&buf->list, &inst->dpbbufs);
176207
}
@@ -1371,6 +1402,24 @@ venus_helper_find_buf(struct venus_inst *inst, unsigned int type, u32 idx)
13711402
}
13721403
EXPORT_SYMBOL_GPL(venus_helper_find_buf);
13731404

1405+
void venus_helper_change_dpb_owner(struct venus_inst *inst,
1406+
struct vb2_v4l2_buffer *vbuf, unsigned int type,
1407+
unsigned int buf_type, u32 tag)
1408+
{
1409+
struct intbuf *dpb_buf;
1410+
1411+
if (!V4L2_TYPE_IS_CAPTURE(type) ||
1412+
buf_type != inst->dpb_buftype)
1413+
return;
1414+
1415+
list_for_each_entry(dpb_buf, &inst->dpbbufs, list)
1416+
if (dpb_buf->dpb_out_tag == tag) {
1417+
dpb_buf->owned_by = DRIVER;
1418+
break;
1419+
}
1420+
}
1421+
EXPORT_SYMBOL_GPL(venus_helper_change_dpb_owner);
1422+
13741423
int venus_helper_vb2_buf_init(struct vb2_buffer *vb)
13751424
{
13761425
struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ struct venus_core;
1414
bool venus_helper_check_codec(struct venus_inst *inst, u32 v4l2_pixfmt);
1515
struct vb2_v4l2_buffer *venus_helper_find_buf(struct venus_inst *inst,
1616
unsigned int type, u32 idx);
17+
void venus_helper_change_dpb_owner(struct venus_inst *inst,
18+
struct vb2_v4l2_buffer *vbuf, unsigned int type,
19+
unsigned int buf_type, u32 idx);
1720
void venus_helper_buffers_done(struct venus_inst *inst, unsigned int type,
1821
enum vb2_buffer_state state);
1922
int venus_helper_vb2_buf_init(struct vb2_buffer *vb);

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1339,8 +1339,10 @@ static void vdec_buf_done(struct venus_inst *inst, unsigned int buf_type,
13391339
type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
13401340

13411341
vbuf = venus_helper_find_buf(inst, type, tag);
1342-
if (!vbuf)
1342+
if (!vbuf) {
1343+
venus_helper_change_dpb_owner(inst, vbuf, type, buf_type, tag);
13431344
return;
1345+
}
13441346

13451347
vbuf->flags = flags;
13461348
vbuf->field = V4L2_FIELD_NONE;
@@ -1622,6 +1624,8 @@ static int vdec_open(struct file *file)
16221624

16231625
vdec_inst_init(inst);
16241626

1627+
ida_init(&inst->dpb_ids);
1628+
16251629
/*
16261630
* create m2m device for every instance, the m2m context scheduling
16271631
* is made by firmware side so we do not need to care about.
@@ -1667,6 +1671,7 @@ static int vdec_close(struct file *file)
16671671
v4l2_m2m_ctx_release(inst->m2m_ctx);
16681672
v4l2_m2m_release(inst->m2m_dev);
16691673
vdec_ctrl_deinit(inst);
1674+
ida_destroy(&inst->dpb_ids);
16701675
hfi_session_destroy(inst);
16711676
mutex_destroy(&inst->lock);
16721677
v4l2_fh_del(&inst->fh);

0 commit comments

Comments
 (0)