summaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorYunfei Dong <yunfei.dong@mediatek.com>2023-02-01 07:33:15 +0000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2023-05-11 23:17:07 +0900
commit13c22f8f822f680d767adb3d68f6d2a494797cb3 (patch)
tree290b3f6b70bdfff26b316c58fb7f8447df0ccac3 /drivers/media
parentd3a8364c1edfdfa7905ec680f178f92d73daad45 (diff)
downloadlinux-stable-13c22f8f822f680d767adb3d68f6d2a494797cb3.tar.gz
linux-stable-13c22f8f822f680d767adb3d68f6d2a494797cb3.tar.bz2
linux-stable-13c22f8f822f680d767adb3d68f6d2a494797cb3.zip
media: mediatek: vcodec: making sure queue_work successfully
[ Upstream commit 2e0ef56d81cb2569624d288b7e95a8a2734a7c74 ] 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 <yunfei.dong@mediatek.com> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c31
-rw-r--r--drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h2
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;
};
/**