media: mediatek: vcodec: move core context from device to each instance

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: 2cfca6c1bf ("media: mediatek: vcodec: move lat_buf to the top of core list")
Signed-off-by: Yunfei Dong <yunfei.dong@mediatek.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
This commit is contained in:
Yunfei Dong 2023-05-25 02:40:08 +01:00 committed by Mauro Carvalho Chehab
parent 2864e304fa
commit 297160d411
7 changed files with 26 additions and 46 deletions

View File

@ -310,7 +310,6 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
} }
if (IS_VDEC_LAT_ARCH(dev->vdec_pdata->hw_arch)) { 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 = dev->core_workqueue =
alloc_ordered_workqueue("core-decoder", alloc_ordered_workqueue("core-decoder",
WQ_MEM_RECLAIM | WQ_FREEZABLE); WQ_MEM_RECLAIM | WQ_FREEZABLE);

View File

@ -462,7 +462,6 @@ struct mtk_vcodec_enc_pdata {
* @enc_capability: used to identify encode capability * @enc_capability: used to identify encode capability
* *
* @core_workqueue: queue used for core hardware decode * @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_dev: subdev hardware device
* @subdev_prob_done: check whether all used hw device is prob done * @subdev_prob_done: check whether all used hw device is prob done
@ -511,7 +510,6 @@ struct mtk_vcodec_dev {
unsigned int enc_capability; unsigned int enc_capability;
struct workqueue_struct *core_workqueue; struct workqueue_struct *core_workqueue;
struct vdec_msg_queue_ctx msg_queue_core_ctx;
void *subdev_dev[MTK_VDEC_HW_MAX]; void *subdev_dev[MTK_VDEC_HW_MAX];
int (*subdev_prob_done)(struct mtk_vcodec_dev *vdec_dev); int (*subdev_prob_done)(struct mtk_vcodec_dev *vdec_dev);

View File

@ -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)) { if (IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability)) {
memcpy(&share_info->h264_slice_params, &inst->vsi->h264_slice_params, memcpy(&share_info->h264_slice_params, &inst->vsi->h264_slice_params,
sizeof(share_info->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 */ /* 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)) { if (!IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability)) {
memcpy(&share_info->h264_slice_params, &inst->vsi->h264_slice_params, memcpy(&share_info->h264_slice_params, &inst->vsi->h264_slice_params,
sizeof(share_info->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, 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]); inst->vsi->dec.crc[0], inst->vsi->dec.crc[1], inst->vsi->dec.crc[2]);

View File

@ -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)) { if (IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability)) {
memcpy(&share_info->hevc_slice_params, &inst->vsi->hevc_slice_params, memcpy(&share_info->hevc_slice_params, &inst->vsi->hevc_slice_params,
sizeof(share_info->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 */ /* 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)) { if (!IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability)) {
memcpy(&share_info->hevc_slice_params, &inst->vsi->hevc_slice_params, memcpy(&share_info->hevc_slice_params, &inst->vsi->hevc_slice_params,
sizeof(share_info->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, 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]); inst->vsi->dec.crc[0], inst->vsi->dec.crc[1], inst->vsi->dec.crc[2]);

View File

@ -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, vdec_msg_queue_update_ube_wptr(&ctx->msg_queue,
vsi->trans.dma_addr_end + vsi->trans.dma_addr_end +
ctx->msg_queue.wdma_addr.dma_addr); 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; return 0;
err_free_fb_out: err_free_fb_out:

View File

@ -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) bool vdec_msg_queue_wait_lat_buf_full(struct vdec_msg_queue *msg_queue)
{ {
struct vdec_lat_buf *buf, *tmp; int ret;
struct list_head *list_core[3];
struct vdec_msg_queue_ctx *core_ctx;
int ret, i, in_core_count = 0, count = 0;
long timeout_jiff; long timeout_jiff;
core_ctx = &msg_queue->ctx->dev->msg_queue_core_ctx; if (atomic_read(&msg_queue->lat_list_cnt) == NUM_BUFFER_COUNT) {
spin_lock(&core_ctx->ready_lock); mtk_v4l2_debug(3, "wait buf full: list(%d %d) ready_num:%d status:%d",
list_for_each_entry_safe(buf, tmp, &core_ctx->ready_queue, core_list) { atomic_read(&msg_queue->lat_list_cnt),
if (buf && buf->ctx == msg_queue->ctx) { atomic_read(&msg_queue->core_list_cnt),
list_core[in_core_count++] = &buf->core_list; msg_queue->lat_ctx.ready_num,
list_del(&buf->core_list); msg_queue->status);
} return true;
} }
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);
}
spin_unlock(&core_ctx->ready_lock);
timeout_jiff = msecs_to_jiffies(1000 * (NUM_BUFFER_COUNT + 2)); 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, msg_queue->lat_ctx.ready_num == NUM_BUFFER_COUNT,
timeout_jiff); timeout_jiff);
if (ret) { if (ret) {
@ -208,18 +199,9 @@ bool vdec_msg_queue_wait_lat_buf_full(struct vdec_msg_queue *msg_queue)
return true; return true;
} }
spin_lock(&core_ctx->ready_lock); mtk_v4l2_err("failed with lat buf isn't full: list(%d %d)",
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->lat_list_cnt),
atomic_read(&msg_queue->core_list_cnt), count); atomic_read(&msg_queue->core_list_cnt));
return false; return false;
} }
@ -247,6 +229,8 @@ void vdec_msg_queue_deinit(struct vdec_msg_queue *msg_queue,
kfree(lat_buf->private_data); kfree(lat_buf->private_data);
} }
cancel_work_sync(&msg_queue->core_work);
} }
static void vdec_msg_queue_core_work(struct work_struct *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 mtk_vcodec_dev *dev = ctx->dev;
struct vdec_lat_buf *lat_buf; 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; 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) if (!lat_buf)
return; 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); mtk_vcodec_dec_disable_hardware(ctx, MTK_VDEC_CORE);
vdec_msg_queue_qbuf(&ctx->msg_queue.lat_ctx, lat_buf); 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) && if (!(ctx->msg_queue.status & CONTEXT_LIST_QUEUED) &&
atomic_read(&msg_queue->core_list_cnt)) { 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; 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); 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) if (msg_queue->wdma_addr.size)
return 0; 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->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); INIT_WORK(&msg_queue->core_work, vdec_msg_queue_core_work);
atomic_set(&msg_queue->lat_list_cnt, 0); atomic_set(&msg_queue->lat_list_cnt, 0);

View File

@ -84,7 +84,7 @@ struct vdec_lat_buf {
* @wdma_wptr_addr: ube write point * @wdma_wptr_addr: ube write point
* @core_work: core hardware work * @core_work: core hardware work
* @lat_ctx: used to store lat buffer list * @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 * @lat_list_cnt: used to record each instance lat list count
* @core_list_cnt: used to record each instance core 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 work_struct core_work;
struct vdec_msg_queue_ctx lat_ctx; 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 lat_list_cnt;
atomic_t core_list_cnt; atomic_t core_list_cnt;