1: Getting decoder under flow error randomly when do stress test with youtube;
2: Video display black when do plt test with one night.
patch 1 avoid unneeded error logging.
patch 2 using decoder status instead of core work count.
patch 3 move core context from device to each instance.
patch 4 using empty lat buffer as the last one to flush decoder.
---
changed with v3:
- rebase to the top of hevc patch and fix patch 3 build error.
changed with v2:
- fix build error for patch 4
changed with v1:
- re-write commit messgage for patch 1
- squash v1 patch 2 to v1 patch 3 for patch 2
- squash v1 patch 4 to v1 patch 6 for patch 4
---
Yunfei Dong (4):
media: mediatek: vcodec: Avoid unneeded error logging
media: mediatek: vcodec: using decoder status instead of core work
count
media: mediatek: vcodec: move core context from device to each
instance
media: mediatek: vcodec: using empty lat buffer as the last one
.../mediatek/vcodec/mtk_vcodec_dec_drv.c | 1 -
.../vcodec/mtk_vcodec_dec_stateless.c | 2 +-
.../platform/mediatek/vcodec/mtk_vcodec_drv.h | 2 -
.../vcodec/vdec/vdec_h264_req_multi_if.c | 6 +-
.../vcodec/vdec/vdec_hevc_req_multi_if.c | 4 +-
.../vcodec/vdec/vdec_vp9_req_lat_if.c | 4 +-
.../platform/mediatek/vcodec/vdec_msg_queue.c | 105 ++++++++----------
.../platform/mediatek/vcodec/vdec_msg_queue.h | 28 ++++-
8 files changed, 76 insertions(+), 76 deletions(-)
--
2.18.0
Adding one empty lat buffer with parameter 'is_empty_flag = true'
used to flush core work queue decode.
Queue the empty lat buffer to core list when driver need to flush decode.
It's mean core already decode all existed lat buffer when get empty lat
buffer, then wake up core decode done event, the driver will exit when getting
core dec done event.
Fixes: d227af847ac2 ("media: mediatek: vcodec: add core decode done event")
Signed-off-by: Yunfei Dong <[email protected]>
---
.../platform/mediatek/vcodec/vdec_msg_queue.c | 35 +++++++++++--------
.../platform/mediatek/vcodec/vdec_msg_queue.h | 8 +++++
2 files changed, 28 insertions(+), 15 deletions(-)
diff --git a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c
index 3f571cbc8331..66b4175601e3 100644
--- a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c
+++ b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c
@@ -177,9 +177,6 @@ void vdec_msg_queue_update_ube_wptr(struct vdec_msg_queue *msg_queue, uint64_t u
bool vdec_msg_queue_wait_lat_buf_full(struct vdec_msg_queue *msg_queue)
{
- int ret;
- long timeout_jiff;
-
if (atomic_read(&msg_queue->lat_list_cnt) == NUM_BUFFER_COUNT) {
mtk_v4l2_debug(3, "wait buf full: list(%d %d) ready_num:%d status:%d",
atomic_read(&msg_queue->lat_list_cnt),
@@ -189,19 +186,14 @@ bool vdec_msg_queue_wait_lat_buf_full(struct vdec_msg_queue *msg_queue)
return true;
}
- timeout_jiff = msecs_to_jiffies(1000 * (NUM_BUFFER_COUNT + 2));
- ret = wait_event_timeout(msg_queue->core_dec_done,
- msg_queue->lat_ctx.ready_num == NUM_BUFFER_COUNT,
- timeout_jiff);
- if (ret) {
- mtk_v4l2_debug(3, "success to get lat buf: %d",
- msg_queue->lat_ctx.ready_num);
- return true;
- }
+ msg_queue->flush_done = false;
+ vdec_msg_queue_qbuf(&msg_queue->core_ctx, &msg_queue->empty_lat_buf);
+ wait_event(msg_queue->core_dec_done, msg_queue->flush_done);
- mtk_v4l2_err("failed with lat buf isn't full: list(%d %d)",
- atomic_read(&msg_queue->lat_list_cnt),
- atomic_read(&msg_queue->core_list_cnt));
+ mtk_v4l2_debug(3, "flush done => ready_num:%d status:%d list(%d %d)",
+ msg_queue->lat_ctx.ready_num, msg_queue->status,
+ atomic_read(&msg_queue->lat_list_cnt),
+ atomic_read(&msg_queue->core_list_cnt));
return false;
}
@@ -250,6 +242,14 @@ static void vdec_msg_queue_core_work(struct work_struct *work)
if (!lat_buf)
return;
+ if (lat_buf->is_last_frame) {
+ ctx->msg_queue.status = CONTEXT_LIST_DEC_DONE;
+ msg_queue->flush_done = true;
+ wake_up(&ctx->msg_queue.core_dec_done);
+
+ return;
+ }
+
ctx = lat_buf->ctx;
mtk_vcodec_dec_enable_hardware(ctx, MTK_VDEC_CORE);
mtk_vcodec_set_curr_ctx(dev, ctx, MTK_VDEC_CORE);
@@ -300,6 +300,10 @@ int vdec_msg_queue_init(struct vdec_msg_queue *msg_queue,
msg_queue->wdma_rptr_addr = msg_queue->wdma_addr.dma_addr;
msg_queue->wdma_wptr_addr = msg_queue->wdma_addr.dma_addr;
+ msg_queue->empty_lat_buf.ctx = ctx;
+ msg_queue->empty_lat_buf.core_decode = NULL;
+ msg_queue->empty_lat_buf.is_last_frame = true;
+
for (i = 0; i < NUM_BUFFER_COUNT; i++) {
lat_buf = &msg_queue->lat_buf[i];
@@ -325,6 +329,7 @@ int vdec_msg_queue_init(struct vdec_msg_queue *msg_queue,
lat_buf->ctx = ctx;
lat_buf->core_decode = core_decode;
+ lat_buf->is_last_frame = false;
err = vdec_msg_queue_qbuf(&msg_queue->lat_ctx, lat_buf);
if (err) {
mtk_v4l2_err("failed to qbuf buf[%d]", i);
diff --git a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h
index efc94165e016..8f771874f8e6 100644
--- a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h
+++ b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h
@@ -62,6 +62,8 @@ struct vdec_msg_queue_ctx {
* @core_decode: different codec use different decode callback function
* @lat_list: add lat buffer to lat head list
* @core_list: add lat buffer to core head list
+ *
+ * @is_last_frame: meaning this buffer is the last frame
*/
struct vdec_lat_buf {
struct mtk_vcodec_mem wdma_err_addr;
@@ -74,6 +76,8 @@ struct vdec_lat_buf {
core_decode_cb_t core_decode;
struct list_head lat_list;
struct list_head core_list;
+
+ bool is_last_frame;
};
/**
@@ -88,6 +92,8 @@ 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
+ * @flush_done: core flush done status
+ * @empty_lat_buf: the last lat buf used to flush decode
* @core_dec_done: core work queue decode done event
* @status: current context decode status for core hardware
*/
@@ -104,6 +110,8 @@ struct vdec_msg_queue {
atomic_t lat_list_cnt;
atomic_t core_list_cnt;
+ bool flush_done;
+ struct vdec_lat_buf empty_lat_buf;
wait_queue_head_t core_dec_done;
int status;
};
--
2.18.0
There are so many lat buffer in core context list, some instances
maybe be scheduled for a very long time. Moving the core context to
each instance, it only be used to control lat buffer of each instance.
And the core work queue of each instance is scheduled by system.
Fixes: 2cfca6c1bf80 ("media: mediatek: vcodec: move lat_buf to the top of core list")
Signed-off-by: Yunfei Dong <[email protected]>
---
.../mediatek/vcodec/mtk_vcodec_dec_drv.c | 1 -
.../platform/mediatek/vcodec/mtk_vcodec_drv.h | 2 -
.../vcodec/vdec/vdec_h264_req_multi_if.c | 4 +-
.../vcodec/vdec/vdec_hevc_req_multi_if.c | 4 +-
.../vcodec/vdec/vdec_vp9_req_lat_if.c | 2 +-
.../platform/mediatek/vcodec/vdec_msg_queue.c | 55 +++++++------------
.../platform/mediatek/vcodec/vdec_msg_queue.h | 4 +-
7 files changed, 26 insertions(+), 46 deletions(-)
diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c
index 9c652beb3f19..7bd300341cf0 100644
--- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c
+++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c
@@ -310,7 +310,6 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
}
if (IS_VDEC_LAT_ARCH(dev->vdec_pdata->hw_arch)) {
- vdec_msg_queue_init_ctx(&dev->msg_queue_core_ctx, MTK_VDEC_CORE);
dev->core_workqueue =
alloc_ordered_workqueue("core-decoder",
WQ_MEM_RECLAIM | WQ_FREEZABLE);
diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h
index 144252fa8bea..1f4c5774ec47 100644
--- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h
+++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h
@@ -462,7 +462,6 @@ struct mtk_vcodec_enc_pdata {
* @enc_capability: used to identify encode capability
*
* @core_workqueue: queue used for core hardware decode
- * @msg_queue_core_ctx: msg queue context used for core workqueue
*
* @subdev_dev: subdev hardware device
* @subdev_prob_done: check whether all used hw device is prob done
@@ -511,7 +510,6 @@ struct mtk_vcodec_dev {
unsigned int enc_capability;
struct workqueue_struct *core_workqueue;
- struct vdec_msg_queue_ctx msg_queue_core_ctx;
void *subdev_dev[MTK_VDEC_HW_MAX];
int (*subdev_prob_done)(struct mtk_vcodec_dev *vdec_dev);
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 181cc52e0847..a7e8e3257b7f 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
@@ -672,7 +672,7 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
if (IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability)) {
memcpy(&share_info->h264_slice_params, &inst->vsi->h264_slice_params,
sizeof(share_info->h264_slice_params));
- vdec_msg_queue_qbuf(&inst->ctx->dev->msg_queue_core_ctx, lat_buf);
+ vdec_msg_queue_qbuf(&inst->ctx->msg_queue.core_ctx, lat_buf);
}
/* wait decoder done interrupt */
@@ -698,7 +698,7 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
if (!IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability)) {
memcpy(&share_info->h264_slice_params, &inst->vsi->h264_slice_params,
sizeof(share_info->h264_slice_params));
- vdec_msg_queue_qbuf(&inst->ctx->dev->msg_queue_core_ctx, lat_buf);
+ vdec_msg_queue_qbuf(&inst->ctx->msg_queue.core_ctx, lat_buf);
}
mtk_vcodec_debug(inst, "dec num: %d lat crc: 0x%x 0x%x 0x%x", inst->slice_dec_num,
inst->vsi->dec.crc[0], inst->vsi->dec.crc[1], inst->vsi->dec.crc[2]);
diff --git a/drivers/media/platform/mediatek/vcodec/vdec/vdec_hevc_req_multi_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_hevc_req_multi_if.c
index 26c04421dca5..97b6da2c3995 100644
--- a/drivers/media/platform/mediatek/vcodec/vdec/vdec_hevc_req_multi_if.c
+++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_hevc_req_multi_if.c
@@ -1017,7 +1017,7 @@ static int vdec_hevc_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
if (IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability)) {
memcpy(&share_info->hevc_slice_params, &inst->vsi->hevc_slice_params,
sizeof(share_info->hevc_slice_params));
- vdec_msg_queue_qbuf(&inst->ctx->dev->msg_queue_core_ctx, lat_buf);
+ vdec_msg_queue_qbuf(&inst->ctx->msg_queue.core_ctx, lat_buf);
}
/* wait decoder done interrupt */
@@ -1043,7 +1043,7 @@ static int vdec_hevc_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
if (!IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability)) {
memcpy(&share_info->hevc_slice_params, &inst->vsi->hevc_slice_params,
sizeof(share_info->hevc_slice_params));
- vdec_msg_queue_qbuf(&inst->ctx->dev->msg_queue_core_ctx, lat_buf);
+ vdec_msg_queue_qbuf(&inst->ctx->msg_queue.core_ctx, lat_buf);
}
mtk_vcodec_debug(inst, "dec num: %d lat crc: 0x%x 0x%x 0x%x", inst->slice_dec_num,
inst->vsi->dec.crc[0], inst->vsi->dec.crc[1], inst->vsi->dec.crc[2]);
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 6d981d7341d2..c2f90848f498 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
@@ -2119,7 +2119,7 @@ static int vdec_vp9_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
vdec_msg_queue_update_ube_wptr(&ctx->msg_queue,
vsi->trans.dma_addr_end +
ctx->msg_queue.wdma_addr.dma_addr);
- vdec_msg_queue_qbuf(&ctx->dev->msg_queue_core_ctx, lat_buf);
+ vdec_msg_queue_qbuf(&ctx->msg_queue.core_ctx, lat_buf);
return 0;
err_free_fb_out:
diff --git a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c
index 03f8d7cd8edd..3f571cbc8331 100644
--- a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c
+++ b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c
@@ -177,29 +177,20 @@ void vdec_msg_queue_update_ube_wptr(struct vdec_msg_queue *msg_queue, uint64_t u
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, count = 0;
+ int ret;
long timeout_jiff;
- core_ctx = &msg_queue->ctx->dev->msg_queue_core_ctx;
- 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) {
- list_core[in_core_count++] = &buf->core_list;
- list_del(&buf->core_list);
- }
- }
-
- for (i = 0; i < in_core_count; i++) {
- list_add(list_core[in_core_count - (1 + i)], &core_ctx->ready_queue);
- queue_work(msg_queue->ctx->dev->core_workqueue, &msg_queue->core_work);
+ if (atomic_read(&msg_queue->lat_list_cnt) == NUM_BUFFER_COUNT) {
+ mtk_v4l2_debug(3, "wait buf full: list(%d %d) ready_num:%d status:%d",
+ atomic_read(&msg_queue->lat_list_cnt),
+ atomic_read(&msg_queue->core_list_cnt),
+ msg_queue->lat_ctx.ready_num,
+ msg_queue->status);
+ return true;
}
- spin_unlock(&core_ctx->ready_lock);
timeout_jiff = msecs_to_jiffies(1000 * (NUM_BUFFER_COUNT + 2));
- ret = wait_event_timeout(msg_queue->ctx->msg_queue.core_dec_done,
+ ret = wait_event_timeout(msg_queue->core_dec_done,
msg_queue->lat_ctx.ready_num == NUM_BUFFER_COUNT,
timeout_jiff);
if (ret) {
@@ -208,18 +199,9 @@ bool vdec_msg_queue_wait_lat_buf_full(struct vdec_msg_queue *msg_queue)
return true;
}
- 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",
+ mtk_v4l2_err("failed with lat buf isn't full: list(%d %d)",
atomic_read(&msg_queue->lat_list_cnt),
- atomic_read(&msg_queue->core_list_cnt), count);
+ atomic_read(&msg_queue->core_list_cnt));
return false;
}
@@ -247,6 +229,8 @@ void vdec_msg_queue_deinit(struct vdec_msg_queue *msg_queue,
kfree(lat_buf->private_data);
}
+
+ cancel_work_sync(&msg_queue->core_work);
}
static void vdec_msg_queue_core_work(struct work_struct *work)
@@ -258,11 +242,11 @@ static void vdec_msg_queue_core_work(struct work_struct *work)
struct mtk_vcodec_dev *dev = ctx->dev;
struct vdec_lat_buf *lat_buf;
- spin_lock(&ctx->dev->msg_queue_core_ctx.ready_lock);
+ spin_lock(&msg_queue->core_ctx.ready_lock);
ctx->msg_queue.status &= ~CONTEXT_LIST_QUEUED;
- spin_unlock(&ctx->dev->msg_queue_core_ctx.ready_lock);
+ spin_unlock(&msg_queue->core_ctx.ready_lock);
- lat_buf = vdec_msg_queue_dqbuf(&dev->msg_queue_core_ctx);
+ lat_buf = vdec_msg_queue_dqbuf(&msg_queue->core_ctx);
if (!lat_buf)
return;
@@ -276,12 +260,11 @@ 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 (!(ctx->msg_queue.status & CONTEXT_LIST_QUEUED) &&
atomic_read(&msg_queue->core_list_cnt)) {
- spin_lock(&ctx->dev->msg_queue_core_ctx.ready_lock);
+ spin_lock(&msg_queue->core_ctx.ready_lock);
ctx->msg_queue.status |= CONTEXT_LIST_QUEUED;
- spin_unlock(&ctx->dev->msg_queue_core_ctx.ready_lock);
+ spin_unlock(&msg_queue->core_ctx.ready_lock);
queue_work(ctx->dev->core_workqueue, &msg_queue->core_work);
}
}
@@ -297,8 +280,8 @@ int vdec_msg_queue_init(struct vdec_msg_queue *msg_queue,
if (msg_queue->wdma_addr.size)
return 0;
- msg_queue->ctx = ctx;
vdec_msg_queue_init_ctx(&msg_queue->lat_ctx, MTK_VDEC_LAT0);
+ vdec_msg_queue_init_ctx(&msg_queue->core_ctx, MTK_VDEC_CORE);
INIT_WORK(&msg_queue->core_work, vdec_msg_queue_core_work);
atomic_set(&msg_queue->lat_list_cnt, 0);
diff --git a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h
index 8f82d1484772..efc94165e016 100644
--- a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h
+++ b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h
@@ -84,7 +84,7 @@ struct vdec_lat_buf {
* @wdma_wptr_addr: ube write point
* @core_work: core hardware work
* @lat_ctx: used to store lat buffer list
- * @ctx: point to mtk_vcodec_ctx
+ * @core_ctx: used to store core buffer list
*
* @lat_list_cnt: used to record each instance lat list count
* @core_list_cnt: used to record each instance core list count
@@ -100,7 +100,7 @@ struct vdec_msg_queue {
struct work_struct core_work;
struct vdec_msg_queue_ctx lat_ctx;
- struct mtk_vcodec_ctx *ctx;
+ struct vdec_msg_queue_ctx core_ctx;
atomic_t lat_list_cnt;
atomic_t core_list_cnt;
--
2.18.0
Il 25/05/23 03:40, Yunfei Dong ha scritto:
> Adding one empty lat buffer with parameter 'is_empty_flag = true'
> used to flush core work queue decode.
>
> Queue the empty lat buffer to core list when driver need to flush decode.
> It's mean core already decode all existed lat buffer when get empty lat
> buffer, then wake up core decode done event, the driver will exit when getting
> core dec done event.
>
> Fixes: d227af847ac2 ("media: mediatek: vcodec: add core decode done event")
> Signed-off-by: Yunfei Dong <[email protected]>
Reviewed-by: AngeloGioacchino Del Regno <[email protected]>
Il 25/05/23 03:40, Yunfei Dong ha scritto:
> There are so many lat buffer in core context list, some instances
> maybe be scheduled for a very long time. Moving the core context to
> each instance, it only be used to control lat buffer of each instance.
> And the core work queue of each instance is scheduled by system.
>
> Fixes: 2cfca6c1bf80 ("media: mediatek: vcodec: move lat_buf to the top of core list")
> Signed-off-by: Yunfei Dong <[email protected]>
Reviewed-by: AngeloGioacchino Del Regno <[email protected]>
On Thu, May 25, 2023 at 09:40:08AM +0800, Yunfei Dong wrote:
[..]
> --- a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c
> +++ b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c
[..]
> @@ -247,6 +229,8 @@ void vdec_msg_queue_deinit(struct vdec_msg_queue *msg_queue,
>
> kfree(lat_buf->private_data);
> }
> +
> + cancel_work_sync(&msg_queue->core_work);
Hi Yunfei,
this hunk is causing warnings during boot and when exercising the decoder with
fluster on mt8192-asurada-spherion. This deinit function is called on the
v4l2 release callback, even though the work might not have been initialized as
that only happens if/when the codec specific 'decode' callback is called (as a
result of device_run m2m callback).
Thanks,
N?colas
<4>[ 496.164381] ------------[ cut here ]------------
<4>[ 496.169259] WARNING: CPU: 5 PID: 2338 at kernel/workqueue.c:3376 __flush_work.isra.0+0x23c/0x258
<4>[ 496.178299] Modules linked in: r8153_ecm cdc_ether usbnet r8152 mt7921e mt7921_common mt76_connac_lib mt76 mac80211 btusb btintel btmtk btrtl btbcm cfg80211 bluetooth uvcvideo mt8192_mt6359_rt1015_rt5682 uvc ecdh_generic snd_soc_mt8192_afe ecc videobuf2_vmalloc crct10dif_ce cros_usbpd_logger fuse ip_tables ipv6
<4>[ 496.206108] CPU: 5 PID: 2338 Comm: gst-launch-1.0 Tainted: G W 6.4.0-rc5-next-20230607+ #475
<4>[ 496.216182] Hardware name: Google Spherion (rev0 - 3) (DT)
<4>[ 496.221915] pstate: 00400009 (nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
<4>[ 496.229125] pc : __flush_work.isra.0+0x23c/0x258
<4>[ 496.233992] lr : __cancel_work_timer+0x14c/0x1c8
<4>[ 496.238859] sp : ffff8000896e3b00
<4>[ 496.242423] x29: ffff8000896e3b00 x28: ffff57c3d4079f80 x27: 0000000000000000
<4>[ 496.249807] x26: ffff57c3d4079f80 x25: ffffb76395b59dc8 x24: 0000000000000001
<4>[ 496.257191] x23: ffffb763928daab8 x22: ffff57c3d4079f80 x21: 0000000000000000
<4>[ 496.264575] x20: ffffb763955f6778 x19: ffff57c3cf06f4a0 x18: 0000000000000000
<4>[ 496.271958] x17: 000000040044ffff x16: 005000f2b5503510 x15: 0000000000000000
<4>[ 496.279342] x14: ffff57c3c03a1f80 x13: ffffa0616a2fc000 x12: 000000003464d91d
<4>[ 496.286726] x11: 0000000000000000 x10: 0000000000001b10 x9 : ffffb763928de61c
<4>[ 496.294110] x8 : ffff57c3d407baf0 x7 : 0000000000000000 x6 : ffff57c3d4079f80
<4>[ 496.301494] x5 : ffff57c3d4079f80 x4 : 0000000000000000 x3 : 0000000000000000
<4>[ 496.308878] x2 : ffff8000896e3bf0 x1 : 0000000000000011 x0 : 0000000000000000
<4>[ 496.316262] Call trace:
<4>[ 496.318958] __flush_work.isra.0+0x23c/0x258
<4>[ 496.323477] __cancel_work_timer+0x14c/0x1c8
<4>[ 496.327996] cancel_work_sync+0x1c/0x30
<4>[ 496.332082] vdec_msg_queue_deinit+0xac/0xc8
<4>[ 496.336604] vdec_h264_slice_deinit+0x64/0xb8
<4>[ 496.341211] vdec_if_deinit+0x3c/0x68
<4>[ 496.345123] mtk_vcodec_dec_release+0x20/0x40
<4>[ 496.349729] fops_vcodec_release+0x50/0xd8
<4>[ 496.354074] v4l2_release+0x7c/0x100
<4>[ 496.357900] __fput+0x80/0x270
<4>[ 496.361205] ____fput+0x18/0x30
<4>[ 496.364595] task_work_run+0x78/0xe0
<4>[ 496.368420] do_notify_resume+0x29c/0x7f8
<4>[ 496.372680] el0_svc+0xa4/0xb8
<4>[ 496.375987] el0t_64_sync_handler+0xc0/0xc8
<4>[ 496.380423] el0t_64_sync+0x1a8/0x1b0
<4>[ 496.384336] ---[ end trace 0000000000000000 ]---