linux (Allwinner): cedrus fixes for Linux 6.0

This commit is contained in:
Rudi Heitbaum 2022-10-04 19:48:20 +00:00
parent f1bea96ff5
commit 3a3b2bd6de
3 changed files with 179 additions and 0 deletions

View File

@ -0,0 +1,26 @@
From 566615d14dd8b4a5dbc06f158cb35450b1105e35 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@gmail.com>
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 <jernej.skrabec@gmail.com>
---
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;

View File

@ -0,0 +1,91 @@
From e85edafea5122a1357c884559db1a00046102807 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@gmail.com>
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 <jernej.skrabec@gmail.com>
---
.../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

View File

@ -0,0 +1,62 @@
From: Nicolas Dufresne <nicolas.dufresne@collabora.com>
To: linux-media@vger.kernel.org, Maxime Ripard <mripard@kernel.org>,
Paul Kocialkowski <paul.kocialkowski@bootlin.com>,
Mauro Carvalho Chehab <mchehab@kernel.org>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Chen-Yu Tsai <wens@csie.org>,
Jernej Skrabec <jernej.skrabec@gmail.com>,
Samuel Holland <samuel@sholland.org>,
Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>,
Hans Verkuil <hverkuil-cisco@xs4all.nl>
Cc: kernel@collabora.com,
Nicolas Dufresne <nicolas.dufresne@collabora.com>,
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 <nicolas.dufresne@collabora.com>
Reviewed-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>
---
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,