diff --git a/projects/Allwinner/patches/linux/0061-media--cedrus--Don-t-CPU-map-source-buffers.patch b/projects/Allwinner/patches/linux/0061-media--cedrus--Don-t-CPU-map-source-buffers.patch new file mode 100644 index 0000000000..1aeb3d60f2 --- /dev/null +++ b/projects/Allwinner/patches/linux/0061-media--cedrus--Don-t-CPU-map-source-buffers.patch @@ -0,0 +1,26 @@ +From 566615d14dd8b4a5dbc06f158cb35450b1105e35 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Tue, 4 Oct 2022 20:36:18 +0200 +Subject: [PATCH] media: cedrus: Don't CPU map source buffers + +There is no need to access source buffers via CPU, so let's disable +that. This will lower amount of virtual memory needed on 32-bit ARM +SoCs. + +Signed-off-by: Jernej Skrabec +--- + drivers/staging/media/sunxi/cedrus/cedrus_video.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c +index f1eb94197a3d6c..8967f221f359f9 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c +@@ -601,6 +601,7 @@ int cedrus_queue_init(void *priv, struct vb2_queue *src_vq, + + src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + src_vq->io_modes = VB2_MMAP | VB2_DMABUF; ++ src_vq->dma_attrs = DMA_ATTR_NO_KERNEL_MAPPING; + src_vq->drv_priv = ctx; + src_vq->buf_struct_size = sizeof(struct cedrus_buffer); + src_vq->ops = &cedrus_qops; diff --git a/projects/Allwinner/patches/linux/0062-media--cedrus--hevc--Fix-offset-adjustments.patch b/projects/Allwinner/patches/linux/0062-media--cedrus--hevc--Fix-offset-adjustments.patch new file mode 100644 index 0000000000..97d93e3864 --- /dev/null +++ b/projects/Allwinner/patches/linux/0062-media--cedrus--hevc--Fix-offset-adjustments.patch @@ -0,0 +1,91 @@ +From e85edafea5122a1357c884559db1a00046102807 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Tue, 4 Oct 2022 20:28:44 +0200 +Subject: [PATCH] media: cedrus: hevc: Fix offset adjustments + +As it turns out, current padding size check works fine in theory but it +doesn't in practice. Most probable reason are caching issues. + +Let's rework reading data from bitstream using Cedrus engine instead of +CPU. That way we avoid all cache issues and make sure that we're reading +same data as Cedrus. + +Fixes: e7060d9a78c2 ("media: uapi: Change data_bit_offset definition") +Signed-off-by: Jernej Skrabec +--- + .../staging/media/sunxi/cedrus/cedrus_h265.c | 24 ++++++++++++++----- + .../staging/media/sunxi/cedrus/cedrus_regs.h | 2 ++ + 2 files changed, 20 insertions(+), 6 deletions(-) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +index 82e2e510e62509..400a7bc1670df3 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +@@ -281,6 +281,17 @@ static void cedrus_h265_skip_bits(struct cedrus_dev *dev, int num) + } + } + ++static u32 cedrus_h265_show_bits(struct cedrus_dev *dev, int num) ++{ ++ cedrus_write(dev, VE_DEC_H265_TRIGGER, ++ VE_DEC_H265_TRIGGER_SHOW_BITS | ++ VE_DEC_H265_TRIGGER_TYPE_N_BITS(num)); ++ while (cedrus_read(dev, VE_DEC_H265_STATUS) & VE_DEC_H265_STATUS_VLD_BUSY) ++ udelay(1); ++ ++ return cedrus_read(dev, VE_DEC_H265_READED_BITS); ++} ++ + static void cedrus_h265_write_scaling_list(struct cedrus_ctx *ctx, + struct cedrus_run *run) + { +@@ -445,7 +456,7 @@ static int cedrus_h265_setup(struct cedrus_ctx *ctx, struct cedrus_run *run) + u32 num_entry_point_offsets; + u32 output_pic_list_index; + u32 pic_order_cnt[2]; +- u8 *padding; ++ u8 padding; + int count; + u32 reg; + +@@ -529,21 +540,22 @@ static int cedrus_h265_setup(struct cedrus_ctx *ctx, struct cedrus_run *run) + if (slice_params->data_byte_offset == 0) + return -EOPNOTSUPP; + +- padding = (u8 *)vb2_plane_vaddr(&run->src->vb2_buf, 0) + +- slice_params->data_byte_offset - 1; ++ cedrus_h265_skip_bits(dev, (slice_params->data_byte_offset - 1) * 8); ++ ++ padding = cedrus_h265_show_bits(dev, 8); + + /* at least one bit must be set in that byte */ +- if (*padding == 0) ++ if (padding == 0) + return -EINVAL; + + for (count = 0; count < 8; count++) +- if (*padding & (1 << count)) ++ if (padding & (1 << count)) + break; + + /* Include the one bit. */ + count++; + +- cedrus_h265_skip_bits(dev, slice_params->data_byte_offset * 8 - count); ++ cedrus_h265_skip_bits(dev, 8 - count); + + /* Bitstream parameters. */ + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h +index 2f7dbd8b8896e9..424049f567c465 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h +@@ -509,6 +509,8 @@ + #define VE_DEC_H265_LOW_ADDR_ENTRY_POINTS_BUF(a) \ + SHIFT_AND_MASK_BITS(a, 7, 0) + ++#define VE_DEC_H265_READED_BITS (VE_ENGINE_DEC_H265 + 0xdc) ++ + #define VE_DEC_H265_SRAM_OFFSET (VE_ENGINE_DEC_H265 + 0xe0) + + #define VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_LUMA_L0 0x00 diff --git a/projects/Allwinner/patches/linux/0064-media--cedrus--Fix-watchdog-race-condition.patch b/projects/Allwinner/patches/linux/0064-media--cedrus--Fix-watchdog-race-condition.patch new file mode 100644 index 0000000000..9904bd7184 --- /dev/null +++ b/projects/Allwinner/patches/linux/0064-media--cedrus--Fix-watchdog-race-condition.patch @@ -0,0 +1,62 @@ +From: Nicolas Dufresne +To: linux-media@vger.kernel.org, Maxime Ripard , + Paul Kocialkowski , + Mauro Carvalho Chehab , + Greg Kroah-Hartman , + Chen-Yu Tsai , + Jernej Skrabec , + Samuel Holland , + Ezequiel Garcia , + Hans Verkuil +Cc: kernel@collabora.com, + Nicolas Dufresne , + stable@vger.kernel.org, linux-staging@lists.linux.dev, + linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, + linux-kernel@vger.kernel.org +Subject: [PATCH v1 1/3] media: cedrus: Fix watchdog race condition +Date: Thu, 18 Aug 2022 16:33:06 -0400 +Message-Id: <20220818203308.439043-2-nicolas.dufresne@collabora.com> +X-Mailer: git-send-email 2.37.2 +In-Reply-To: <20220818203308.439043-1-nicolas.dufresne@collabora.com> +References: <20220818203308.439043-1-nicolas.dufresne@collabora.com> +MIME-Version: 1.0 + +The watchdog needs to be schedule before we trigger the decode +operation, otherwise there is a risk that the decoder IRQ will be +called before we have schedule the watchdog. As a side effect, the +watchdog would never be cancelled and its function would be called +at an inappropriate time. + +This was observed while running Fluster with GStreamer as a backend. +Some programming error would cause the decoder IRQ to be call very +quickly after the trigger. Later calls into the driver would deadlock +due to the unbalanced state. + +Cc: stable@vger.kernel.org +Fixes: 7c38a551bda1 ("media: cedrus: Add watchdog for job completion") +Signed-off-by: Nicolas Dufresne +Reviewed-by: Paul Kocialkowski +Reviewed-by: Jernej Skrabec +--- + drivers/staging/media/sunxi/cedrus/cedrus_dec.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c +index 3b6aa78a2985f..e7f7602a5ab40 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c +@@ -106,11 +106,11 @@ void cedrus_device_run(void *priv) + + /* Trigger decoding if setup went well, bail out otherwise. */ + if (!error) { +- dev->dec_ops[ctx->current_codec]->trigger(ctx); +- + /* Start the watchdog timer. */ + schedule_delayed_work(&dev->watchdog_work, + msecs_to_jiffies(2000)); ++ ++ dev->dec_ops[ctx->current_codec]->trigger(ctx); + } else { + v4l2_m2m_buf_done_and_job_finish(ctx->dev->m2m_dev, + ctx->fh.m2m_ctx, +