2023-01-12 04:22:42

by Yunfei Dong (董云飞)

[permalink] [raw]
Subject: [PATCH v3,0/7] media: mediatek: vcodec: Fix power_VideoCall test fail

Random getting below error message when test power_VideoCall/control.49_vp9:
pc : __list_del_entry_valid+0xb0/0xfc
lr : __list_del_entry_valid+0xac/0xfc

The lat_buf in core list won't be deleted when one instance decode done.
Will access invalid released lat_buf list when queue work continue to decode.
Firstly, remove all unused lat_buf to the top of core list, making sure
these buffers can be decoded in highest priority; lastly, remove all unused
lat_buf when the instance is freed.

patch 1 add params to record lat and core lat_buf count.
patch 2 using each instance lat_buf count replace core ready list.
patch 3 move lat_buf to the top of core list.
patch 4 add core decode done event.
patch 5 remove unused lat_buf.
patch 6 making sure queue_work successfully
patch 7 change lat thread decode error condition
---
changed with v2:
- fix seek fail for patch 3
changed with v1:
- remove mutex for atomic for patch 1
- add patch 6 to make sure queue_work successfully
- add patch 7 change lat thread decode error condition
---
Yunfei Dong (7):
media: mediatek: vcodec: add params to record lat and core lat_buf
count
media: mediatek: vcodec: using each instance lat_buf count replace
core ready list
media: mediatek: vcodec: move lat_buf to the top of core list
media: mediatek: vcodec: add core decode done event
media: mediatek: vcodec: remove unused lat_buf
media: mediatek: vcodec: making sure queue_work successfully
media: mediatek: vcodec: change lat thread decode error condition

.../vcodec/mtk_vcodec_dec_stateless.c | 6 +-
.../vcodec/vdec/vdec_h264_req_multi_if.c | 2 +-
.../vcodec/vdec/vdec_vp9_req_lat_if.c | 2 +-
.../platform/mediatek/vcodec/vdec_msg_queue.c | 95 ++++++++++++++++---
.../platform/mediatek/vcodec/vdec_msg_queue.h | 12 +++
5 files changed, 100 insertions(+), 17 deletions(-)

--
2.18.0


2023-01-12 04:23:42

by Yunfei Dong (董云飞)

[permalink] [raw]
Subject: [PATCH v3,7/7] media: mediatek: vcodec: change lat thread decode error condition

If lat thread can't get lat buffer, it should be that current instance
don't be schedulded, the driver can't free the src buffer directly.

Fixes: 7b182b8d9c85 ("media: mediatek: vcodec: Refactor get and put capture buffer flow")
Signed-off-by: Yunfei Dong <[email protected]>
---
.../platform/mediatek/vcodec/mtk_vcodec_dec_stateless.c | 6 ++++--
.../platform/mediatek/vcodec/vdec/vdec_h264_req_multi_if.c | 2 +-
.../platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c | 2 +-
3 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateless.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateless.c
index ffbcee04dc26..04beb3f08eea 100644
--- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateless.c
+++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateless.c
@@ -258,8 +258,10 @@ static void mtk_vdec_worker(struct work_struct *work)
if (src_buf_req)
v4l2_ctrl_request_complete(src_buf_req, &ctx->ctrl_hdl);
} else {
- v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
- v4l2_m2m_buf_done(vb2_v4l2_src, state);
+ if (ret != -EAGAIN) {
+ v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+ v4l2_m2m_buf_done(vb2_v4l2_src, state);
+ }
v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
}
}
diff --git a/drivers/media/platform/mediatek/vcodec/vdec/vdec_h264_req_multi_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_h264_req_multi_if.c
index 8f262e86bb05..07774b6a3dbd 100644
--- a/drivers/media/platform/mediatek/vcodec/vdec/vdec_h264_req_multi_if.c
+++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_h264_req_multi_if.c
@@ -574,7 +574,7 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
lat_buf = vdec_msg_queue_dqbuf(&inst->ctx->msg_queue.lat_ctx);
if (!lat_buf) {
mtk_vcodec_err(inst, "failed to get lat buffer");
- return -EINVAL;
+ return -EAGAIN;
}
share_info = lat_buf->private_data;
src_buf_info = container_of(bs, struct mtk_video_dec_buf, bs_buffer);
diff --git a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
index cbb6728b8a40..cf16cf2807f0 100644
--- a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
+++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
@@ -2070,7 +2070,7 @@ static int vdec_vp9_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
lat_buf = vdec_msg_queue_dqbuf(&instance->ctx->msg_queue.lat_ctx);
if (!lat_buf) {
mtk_vcodec_err(instance, "Failed to get VP9 lat buf\n");
- return -EBUSY;
+ return -EAGAIN;
}
pfc = (struct vdec_vp9_slice_pfc *)lat_buf->private_data;
if (!pfc) {
--
2.18.0

2023-01-12 04:34:57

by Yunfei Dong (董云飞)

[permalink] [raw]
Subject: [PATCH v3,4/7] media: mediatek: vcodec: add core decode done event

Need to make sure core decode done before current instance is free.

Fixes: 365e4ba01df4 ("media: mtk-vcodec: Add work queue for core hardware decode")
Signed-off-by: Yunfei Dong <[email protected]>
---
drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c | 4 +++-
drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h | 2 ++
2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c
index 0da6e3e2ef0b..ce7c82e38103 100644
--- a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c
+++ b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c
@@ -196,7 +196,7 @@ bool vdec_msg_queue_wait_lat_buf_full(struct vdec_msg_queue *msg_queue)
spin_unlock(&core_ctx->ready_lock);

timeout_jiff = msecs_to_jiffies(1000 * (NUM_BUFFER_COUNT + 2));
- ret = wait_event_timeout(msg_queue->lat_ctx.ready_to_use,
+ ret = wait_event_timeout(msg_queue->ctx->msg_queue.core_dec_done,
msg_queue->lat_ctx.ready_num == NUM_BUFFER_COUNT,
timeout_jiff);
if (ret) {
@@ -257,6 +257,7 @@ static void vdec_msg_queue_core_work(struct work_struct *work)
mtk_vcodec_dec_disable_hardware(ctx, MTK_VDEC_CORE);
vdec_msg_queue_qbuf(&ctx->msg_queue.lat_ctx, lat_buf);

+ wake_up_all(&ctx->msg_queue.core_dec_done);
if (atomic_read(&lat_buf->ctx->msg_queue.core_list_cnt)) {
mtk_v4l2_debug(3, "re-schedule to decode for core: %d",
dev->msg_queue_core_ctx.ready_num);
@@ -281,6 +282,7 @@ int vdec_msg_queue_init(struct vdec_msg_queue *msg_queue,

atomic_set(&msg_queue->lat_list_cnt, 0);
atomic_set(&msg_queue->core_list_cnt, 0);
+ init_waitqueue_head(&msg_queue->core_dec_done);

msg_queue->wdma_addr.size =
vde_msg_queue_get_trans_size(ctx->picinfo.buf_w,
diff --git a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h
index 56280d6682c5..a75c04418f52 100644
--- a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h
+++ b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h
@@ -76,6 +76,7 @@ struct vdec_lat_buf {
*
* @lat_list_cnt: used to record each instance lat list count
* @core_list_cnt: used to record each instance core list count
+ * @core_dec_done: core work queue decode done event
*/
struct vdec_msg_queue {
struct vdec_lat_buf lat_buf[NUM_BUFFER_COUNT];
@@ -90,6 +91,7 @@ struct vdec_msg_queue {

atomic_t lat_list_cnt;
atomic_t core_list_cnt;
+ wait_queue_head_t core_dec_done;
};

/**
--
2.18.0

2023-01-12 04:35:06

by Yunfei Dong (董云飞)

[permalink] [raw]
Subject: [PATCH v3,6/7] media: mediatek: vcodec: making sure queue_work successfully

Putting core work to work queue using queue_work maybe fail, call
queue_work again when the count of core work in work queue is less
than core_list_cnt, making sure all the buffer in core list can be
scheduled.

Fixes: 365e4ba01df4 ("media: mtk-vcodec: Add work queue for core hardware decode")
Signed-off-by: Yunfei Dong <[email protected]>
---
.../platform/mediatek/vcodec/vdec_msg_queue.c | 31 ++++++++++++++-----
.../platform/mediatek/vcodec/vdec_msg_queue.h | 2 ++
2 files changed, 25 insertions(+), 8 deletions(-)

diff --git a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c
index cdc539a46cb9..f3073d1e7f42 100644
--- a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c
+++ b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c
@@ -71,6 +71,7 @@ static void vdec_msg_queue_dec(struct vdec_msg_queue *msg_queue, int hardware_in
int vdec_msg_queue_qbuf(struct vdec_msg_queue_ctx *msg_ctx, struct vdec_lat_buf *buf)
{
struct list_head *head;
+ int status;

head = vdec_get_buf_list(msg_ctx->hardware_index, buf);
if (!head) {
@@ -83,11 +84,17 @@ int vdec_msg_queue_qbuf(struct vdec_msg_queue_ctx *msg_ctx, struct vdec_lat_buf
msg_ctx->ready_num++;

vdec_msg_queue_inc(&buf->ctx->msg_queue, msg_ctx->hardware_index);
- if (msg_ctx->hardware_index != MTK_VDEC_CORE)
+ if (msg_ctx->hardware_index != MTK_VDEC_CORE) {
wake_up_all(&msg_ctx->ready_to_use);
- else
- queue_work(buf->ctx->dev->core_workqueue,
- &buf->ctx->msg_queue.core_work);
+ } else {
+ if (buf->ctx->msg_queue.core_work_cnt <
+ atomic_read(&buf->ctx->msg_queue.core_list_cnt)) {
+ status = queue_work(buf->ctx->dev->core_workqueue,
+ &buf->ctx->msg_queue.core_work);
+ if (status)
+ buf->ctx->msg_queue.core_work_cnt++;
+ }
+ }

mtk_v4l2_debug(3, "enqueue buf type: %d addr: 0x%p num: %d",
msg_ctx->hardware_index, buf, msg_ctx->ready_num);
@@ -254,6 +261,7 @@ static void vdec_msg_queue_core_work(struct work_struct *work)
container_of(msg_queue, struct mtk_vcodec_ctx, msg_queue);
struct mtk_vcodec_dev *dev = ctx->dev;
struct vdec_lat_buf *lat_buf;
+ int status;

lat_buf = vdec_msg_queue_dqbuf(&dev->msg_queue_core_ctx);
if (!lat_buf)
@@ -270,11 +278,17 @@ static void vdec_msg_queue_core_work(struct work_struct *work)
vdec_msg_queue_qbuf(&ctx->msg_queue.lat_ctx, lat_buf);

wake_up_all(&ctx->msg_queue.core_dec_done);
- if (atomic_read(&lat_buf->ctx->msg_queue.core_list_cnt)) {
- mtk_v4l2_debug(3, "re-schedule to decode for core: %d",
- dev->msg_queue_core_ctx.ready_num);
- queue_work(dev->core_workqueue, &msg_queue->core_work);
+ spin_lock(&dev->msg_queue_core_ctx.ready_lock);
+ lat_buf->ctx->msg_queue.core_work_cnt--;
+
+ if (lat_buf->ctx->msg_queue.core_work_cnt <
+ atomic_read(&lat_buf->ctx->msg_queue.core_list_cnt)) {
+ status = queue_work(lat_buf->ctx->dev->core_workqueue,
+ &lat_buf->ctx->msg_queue.core_work);
+ if (status)
+ lat_buf->ctx->msg_queue.core_work_cnt++;
}
+ spin_unlock(&dev->msg_queue_core_ctx.ready_lock);
}

int vdec_msg_queue_init(struct vdec_msg_queue *msg_queue,
@@ -289,6 +303,7 @@ int vdec_msg_queue_init(struct vdec_msg_queue *msg_queue,
return 0;

msg_queue->ctx = ctx;
+ msg_queue->core_work_cnt = 0;
vdec_msg_queue_init_ctx(&msg_queue->lat_ctx, MTK_VDEC_LAT0);
INIT_WORK(&msg_queue->core_work, vdec_msg_queue_core_work);

diff --git a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h
index a75c04418f52..a5d44bc97c16 100644
--- a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h
+++ b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h
@@ -77,6 +77,7 @@ struct vdec_lat_buf {
* @lat_list_cnt: used to record each instance lat list count
* @core_list_cnt: used to record each instance core list count
* @core_dec_done: core work queue decode done event
+ * @core_work_cnt: the number of core work in work queue
*/
struct vdec_msg_queue {
struct vdec_lat_buf lat_buf[NUM_BUFFER_COUNT];
@@ -92,6 +93,7 @@ struct vdec_msg_queue {
atomic_t lat_list_cnt;
atomic_t core_list_cnt;
wait_queue_head_t core_dec_done;
+ int core_work_cnt;
};

/**
--
2.18.0

2023-01-12 04:36:22

by Yunfei Dong (董云飞)

[permalink] [raw]
Subject: [PATCH v3,5/7] media: mediatek: vcodec: remove unused lat_buf

Remove unused lat_buf from core list, or leading to core list access
NULL point.

Fixes: 365e4ba01df4 ("media: mtk-vcodec: Add work queue for core hardware decode")
Signed-off-by: Yunfei Dong <[email protected]>
---
.../platform/mediatek/vcodec/vdec_msg_queue.c | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c
index ce7c82e38103..cdc539a46cb9 100644
--- a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c
+++ b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c
@@ -177,7 +177,7 @@ bool vdec_msg_queue_wait_lat_buf_full(struct vdec_msg_queue *msg_queue)
struct vdec_lat_buf *buf, *tmp;
struct list_head *list_core[3];
struct vdec_msg_queue_ctx *core_ctx;
- int ret, i, in_core_count = 0;
+ int ret, i, in_core_count = 0, count = 0;
long timeout_jiff;

core_ctx = &msg_queue->ctx->dev->msg_queue_core_ctx;
@@ -204,8 +204,20 @@ bool vdec_msg_queue_wait_lat_buf_full(struct vdec_msg_queue *msg_queue)
msg_queue->lat_ctx.ready_num);
return true;
}
- mtk_v4l2_err("failed with lat buf isn't full: %d",
- msg_queue->lat_ctx.ready_num);
+
+ spin_lock(&core_ctx->ready_lock);
+ list_for_each_entry_safe(buf, tmp, &core_ctx->ready_queue, core_list) {
+ if (buf && buf->ctx == msg_queue->ctx) {
+ count++;
+ list_del(&buf->core_list);
+ }
+ }
+ spin_unlock(&core_ctx->ready_lock);
+
+ mtk_v4l2_err("failed with lat buf isn't full: list(%d %d) count:%d",
+ atomic_read(&msg_queue->lat_list_cnt),
+ atomic_read(&msg_queue->core_list_cnt), count);
+
return false;
}

--
2.18.0

2023-01-12 04:36:22

by Yunfei Dong (董云飞)

[permalink] [raw]
Subject: [PATCH v3,1/7] media: mediatek: vcodec: add params to record lat and core lat_buf count

Using lat_buf to share decoder information between lat and core work
queue, adding params to record the buf count.

Fixes: 365e4ba01df4 ("media: mtk-vcodec: Add work queue for core hardware decode")
Signed-off-by: Yunfei Dong <[email protected]>
---
- remove the mutex for atomic
- for there are only lat and core, no need to use hardware_index for every hardware.
---
.../platform/mediatek/vcodec/vdec_msg_queue.c | 23 ++++++++++++++++++-
.../platform/mediatek/vcodec/vdec_msg_queue.h | 6 +++++
2 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c
index dc2004790a47..3f016c87d722 100644
--- a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c
+++ b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c
@@ -52,6 +52,22 @@ static struct list_head *vdec_get_buf_list(int hardware_index, struct vdec_lat_b
}
}

+static void vdec_msg_queue_inc(struct vdec_msg_queue *msg_queue, int hardware_index)
+{
+ if (hardware_index == MTK_VDEC_CORE)
+ atomic_inc(&msg_queue->core_list_cnt);
+ else
+ atomic_inc(&msg_queue->lat_list_cnt);
+}
+
+static void vdec_msg_queue_dec(struct vdec_msg_queue *msg_queue, int hardware_index)
+{
+ if (hardware_index == MTK_VDEC_CORE)
+ atomic_dec(&msg_queue->core_list_cnt);
+ else
+ atomic_dec(&msg_queue->lat_list_cnt);
+}
+
int vdec_msg_queue_qbuf(struct vdec_msg_queue_ctx *msg_ctx, struct vdec_lat_buf *buf)
{
struct list_head *head;
@@ -66,6 +82,7 @@ int vdec_msg_queue_qbuf(struct vdec_msg_queue_ctx *msg_ctx, struct vdec_lat_buf
list_add_tail(head, &msg_ctx->ready_queue);
msg_ctx->ready_num++;

+ vdec_msg_queue_inc(&buf->ctx->msg_queue, msg_ctx->hardware_index);
if (msg_ctx->hardware_index != MTK_VDEC_CORE)
wake_up_all(&msg_ctx->ready_to_use);
else
@@ -127,6 +144,7 @@ struct vdec_lat_buf *vdec_msg_queue_dqbuf(struct vdec_msg_queue_ctx *msg_ctx)
return NULL;
}
list_del(head);
+ vdec_msg_queue_dec(&buf->ctx->msg_queue, msg_ctx->hardware_index);

msg_ctx->ready_num--;
mtk_v4l2_debug(3, "dqueue buf type:%d addr: 0x%p num: %d",
@@ -241,10 +259,13 @@ int vdec_msg_queue_init(struct vdec_msg_queue *msg_queue,

vdec_msg_queue_init_ctx(&msg_queue->lat_ctx, MTK_VDEC_LAT0);
INIT_WORK(&msg_queue->core_work, vdec_msg_queue_core_work);
+
+ atomic_set(&msg_queue->lat_list_cnt, 0);
+ atomic_set(&msg_queue->core_list_cnt, 0);
+
msg_queue->wdma_addr.size =
vde_msg_queue_get_trans_size(ctx->picinfo.buf_w,
ctx->picinfo.buf_h);
-
err = mtk_vcodec_mem_alloc(ctx, &msg_queue->wdma_addr);
if (err) {
mtk_v4l2_err("failed to allocate wdma_addr buf");
diff --git a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h
index c43d427f5f54..b1aa5572ba49 100644
--- a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h
+++ b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h
@@ -72,6 +72,9 @@ struct vdec_lat_buf {
* @wdma_wptr_addr: ube write point
* @core_work: core hardware work
* @lat_ctx: used to store lat buffer list
+ *
+ * @lat_list_cnt: used to record each instance lat list count
+ * @core_list_cnt: used to record each instance core list count
*/
struct vdec_msg_queue {
struct vdec_lat_buf lat_buf[NUM_BUFFER_COUNT];
@@ -82,6 +85,9 @@ struct vdec_msg_queue {

struct work_struct core_work;
struct vdec_msg_queue_ctx lat_ctx;
+
+ atomic_t lat_list_cnt;
+ atomic_t core_list_cnt;
};

/**
--
2.18.0