* [PATCH v2 0/3] media: verisilicon: fix VEPU1 JPEG encoder writes past the CAPTURE buffer
@ 2026-11-10 12:41 Sergei Khomenkov via B4 Relay
2026-11-10 12:41 ` [PATCH v2 1/3] media: verisilicon: stop the VEPU1 JPEG encoder after an unfinished frame Sergei Khomenkov via B4 Relay
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Sergei Khomenkov via B4 Relay @ 2026-11-10 12:41 UTC (permalink / raw)
To: Nicolas Dufresne, Benjamin Gaignard, Philipp Zabel
Cc: Mauro Carvalho Chehab, Hans Verkuil, Heiko Stuebner,
Ezequiel Garcia, Chen-Yu Tsai, Hugues Fruchet, linux-media,
linux-rockchip, linux-arm-kernel, linux-stm32, linux-kernel,
stable, Sergei Khomenkov
The H1 JPEG encoder is given its stream buffer limit in bytes, but the
register counts 64-bit words, so a stream that does not fit the CAPTURE
buffer is written past its end, up to eight times the buffer size. A
quality 100 frame of noise does not fit the default sizeimage, and
userspace can also set a smaller one.
Patch 1 stops the VEPU1 encoder after a buffer-full interrupt, which
leaves it paused. Patch 2 programs the limit in 64-bit words, rounded
down to whole 64-byte bursts. Patch 3 makes the smallest CAPTURE
sizeimage the 624-byte header plus one burst.
Testing, on an RK3026 (VEPU1) only: without the series the encoder
wrote 230 KB past a default-sized 640x480 buffer and 1.6 MB past a
1920x1088 one. With it, 17 overflowing frames, four of them queued back
to back, stopped at the programmed limit without writing past the plane
and came back with the ERROR flag, one interrupt each and no timeout;
the jobs after them completed, and frames that fit are byte for byte the
same as before. A sizeimage of 1 or 600 now reads back 688.
v4l2-compliance 1.30.1 on the encoder node shows no new failures.
The VEPU2 JPEG encoder writes its limit in bytes the same way, but I
cannot test it, so its limit and interrupt handler are unchanged; the
common patch 3 applies to it as well. The STM32MP25 VENC runs the H1
code of patch 2 and gets patch 3, but not the stop of patch 1. Neither
is tested.
The bugs were found and the patches drafted with an LLM coding
assistant while porting mainline Linux to an RK3026 board.
---
Changes in v2:
- Trim the commit messages and code comments (Nicolas).
- 1/3: clear only the enable bit of H1_REG_ENC_CTRL instead of writing
0 to the register, and add a rate-limited warning per fault bit, as
hantro_g2_irq() does; add the H1_REG_INTERRUPT_* fault bits (Nicolas).
- 3/3: keep max(): it is a floor of header + one burst, the 64-byte
rounding is on the stream limit in 2/3 (Nicolas).
- Move the test numbers from the commit messages to this cover letter.
- Link to v1: https://lore.kernel.org/r/20261109-hantro-buflimit-v1-0-f0b86ce61e66@gmail.com
---
Sergei Khomenkov (3):
media: verisilicon: stop the VEPU1 JPEG encoder after an unfinished frame
media: verisilicon: program the H1 JPEG stream limit in 64-bit words
media: verisilicon: leave room for the JPEG header and one stream burst
.../media/platform/verisilicon/hantro_h1_jpeg_enc.c | 7 ++++++-
drivers/media/platform/verisilicon/hantro_h1_regs.h | 4 ++++
drivers/media/platform/verisilicon/hantro_v4l2.c | 9 +++++++++
drivers/media/platform/verisilicon/rockchip_vpu_hw.c | 18 ++++++++++++++++++
4 files changed, 37 insertions(+), 1 deletion(-)
---
base-commit: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4
change-id: 20261106-hantro-buflimit-055e8029be23
Best regards,
--
Sergei Khomenkov <shomenkow@gmail.com>
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v2 1/3] media: verisilicon: stop the VEPU1 JPEG encoder after an unfinished frame
2026-11-10 12:41 [PATCH v2 0/3] media: verisilicon: fix VEPU1 JPEG encoder writes past the CAPTURE buffer Sergei Khomenkov via B4 Relay
@ 2026-11-10 12:41 ` Sergei Khomenkov via B4 Relay
2026-11-10 12:41 ` [PATCH v2 2/3] media: verisilicon: program the H1 JPEG stream limit in 64-bit words Sergei Khomenkov via B4 Relay
2026-11-10 12:41 ` [PATCH v2 3/3] media: verisilicon: leave room for the JPEG header and one stream burst Sergei Khomenkov via B4 Relay
2 siblings, 0 replies; 4+ messages in thread
From: Sergei Khomenkov via B4 Relay @ 2026-11-10 12:41 UTC (permalink / raw)
To: Nicolas Dufresne, Benjamin Gaignard, Philipp Zabel
Cc: Mauro Carvalho Chehab, Hans Verkuil, Heiko Stuebner,
Ezequiel Garcia, Chen-Yu Tsai, Hugues Fruchet, linux-media,
linux-rockchip, linux-arm-kernel, linux-stm32, linux-kernel,
stable, Sergei Khomenkov
From: Sergei Khomenkov <shomenkow@gmail.com>
When the JPEG stream reaches the stream buffer limit, the H1 raises a
buffer-full interrupt and pauses with the enable bit of H1_REG_ENC_CTRL
still set. rockchip_vpu1_vepu_irq() does not stop it, so the next job is
programmed into the paused encoder and times out.
Clear only the enable bit when an interrupt does not report a finished
frame, and warn (rate limited) about each fault bit that is set, as
hantro_g2_irq() does.
Found with an LLM coding assistant while porting mainline Linux to a
Rockchip RK3026 board; the assistant also drafted this change. Tested
on that board, with the next patch applied: a frame that does not fit
now ends with the ERROR flag and one interrupt, and the following jobs
complete. Not tested on other SoCs.
Fixes: 775fec69008d ("media: add Rockchip VPU JPEG encoder driver")
Cc: stable@vger.kernel.org
Signed-off-by: Sergei Khomenkov <shomenkow@gmail.com>
---
drivers/media/platform/verisilicon/hantro_h1_regs.h | 4 ++++
drivers/media/platform/verisilicon/rockchip_vpu_hw.c | 18 ++++++++++++++++++
2 files changed, 22 insertions(+)
diff --git a/drivers/media/platform/verisilicon/hantro_h1_regs.h b/drivers/media/platform/verisilicon/hantro_h1_regs.h
index 8650cc489392..a7f18683dac1 100644
--- a/drivers/media/platform/verisilicon/hantro_h1_regs.h
+++ b/drivers/media/platform/verisilicon/hantro_h1_regs.h
@@ -11,6 +11,10 @@
/* Encoder registers. */
#define H1_REG_INTERRUPT 0x004
+#define H1_REG_INTERRUPT_TIMEOUT BIT(6)
+#define H1_REG_INTERRUPT_BUFFER_FULL BIT(5)
+#define H1_REG_INTERRUPT_RESET BIT(4)
+#define H1_REG_INTERRUPT_BUS_ERROR BIT(3)
#define H1_REG_INTERRUPT_FRAME_RDY BIT(2)
#define H1_REG_INTERRUPT_DIS_BIT BIT(1)
#define H1_REG_INTERRUPT_BIT BIT(0)
diff --git a/drivers/media/platform/verisilicon/rockchip_vpu_hw.c b/drivers/media/platform/verisilicon/rockchip_vpu_hw.c
index 02673be9878e..d201b058e5e8 100644
--- a/drivers/media/platform/verisilicon/rockchip_vpu_hw.c
+++ b/drivers/media/platform/verisilicon/rockchip_vpu_hw.c
@@ -376,6 +376,24 @@ static irqreturn_t rockchip_vpu1_vepu_irq(int irq, void *dev_id)
state = (status & H1_REG_INTERRUPT_FRAME_RDY) ?
VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR;
+ if (status & H1_REG_INTERRUPT_BUFFER_FULL)
+ dev_warn_ratelimited(vpu->dev, "stream buffer full\n");
+ if (status & H1_REG_INTERRUPT_BUS_ERROR)
+ dev_warn_ratelimited(vpu->dev, "bus error detected\n");
+ if (status & H1_REG_INTERRUPT_TIMEOUT)
+ dev_warn_ratelimited(vpu->dev, "frame encode timed out\n");
+ if (status & H1_REG_INTERRUPT_RESET)
+ dev_warn_ratelimited(vpu->dev, "encoder reset\n");
+
+ /* After a buffer full the encoder pauses, still enabled: stop it. */
+ if (!(status & H1_REG_INTERRUPT_FRAME_RDY)) {
+ u32 ctrl = vepu_read(vpu, H1_REG_ENC_CTRL);
+
+ if (ctrl & H1_REG_ENC_CTRL_EN_BIT)
+ vepu_write(vpu, ctrl & ~H1_REG_ENC_CTRL_EN_BIT,
+ H1_REG_ENC_CTRL);
+ }
+
vepu_write(vpu, 0, H1_REG_INTERRUPT);
vepu_write(vpu, 0, H1_REG_AXI_CTRL);
--
2.53.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v2 2/3] media: verisilicon: program the H1 JPEG stream limit in 64-bit words
2026-11-10 12:41 [PATCH v2 0/3] media: verisilicon: fix VEPU1 JPEG encoder writes past the CAPTURE buffer Sergei Khomenkov via B4 Relay
2026-11-10 12:41 ` [PATCH v2 1/3] media: verisilicon: stop the VEPU1 JPEG encoder after an unfinished frame Sergei Khomenkov via B4 Relay
@ 2026-11-10 12:41 ` Sergei Khomenkov via B4 Relay
2026-11-10 12:41 ` [PATCH v2 3/3] media: verisilicon: leave room for the JPEG header and one stream burst Sergei Khomenkov via B4 Relay
2 siblings, 0 replies; 4+ messages in thread
From: Sergei Khomenkov via B4 Relay @ 2026-11-10 12:41 UTC (permalink / raw)
To: Nicolas Dufresne, Benjamin Gaignard, Philipp Zabel
Cc: Mauro Carvalho Chehab, Hans Verkuil, Heiko Stuebner,
Ezequiel Garcia, Chen-Yu Tsai, Hugues Fruchet, linux-media,
linux-rockchip, linux-arm-kernel, linux-stm32, linux-kernel,
stable, Sergei Khomenkov
From: Sergei Khomenkov <shomenkow@gmail.com>
H1_REG_STR_BUF_LIMIT counts 64-bit words, but the driver writes the room
left in the CAPTURE plane in bytes. A stream that does not fit, such as
a quality 100 frame of noise in a default-sized buffer, is then written
past the end of the plane, up to eight times its size.
Write the limit in 64-bit words, rounded down to whole 64-byte bursts:
the encoder finishes a burst it has started, so an unrounded limit lets
it write up to 56 bytes past it.
Found with an LLM coding assistant while porting mainline Linux to a
Rockchip RK3026 board; the assistant also drafted this change. Tested
on that board: overflowing frames now stop at the programmed limit
without writing past the plane, and frames that fit are byte for byte
the same as before. Not tested on other SoCs, including the STM32MP25,
which shares this code.
Fixes: 775fec69008d ("media: add Rockchip VPU JPEG encoder driver")
Cc: stable@vger.kernel.org
Signed-off-by: Sergei Khomenkov <shomenkow@gmail.com>
---
drivers/media/platform/verisilicon/hantro_h1_jpeg_enc.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/media/platform/verisilicon/hantro_h1_jpeg_enc.c b/drivers/media/platform/verisilicon/hantro_h1_jpeg_enc.c
index 86cc1a07026f..665a87e9fe92 100644
--- a/drivers/media/platform/verisilicon/hantro_h1_jpeg_enc.c
+++ b/drivers/media/platform/verisilicon/hantro_h1_jpeg_enc.c
@@ -55,7 +55,12 @@ static void hantro_h1_jpeg_enc_set_buffers(struct hantro_dev *vpu,
vepu_write_relaxed(vpu, vb2_dma_contig_plane_dma_addr(dst_buf, 0) +
ctx->vpu_dst_fmt->header_size,
H1_REG_ADDR_OUTPUT_STREAM);
- vepu_write_relaxed(vpu, size_left, H1_REG_STR_BUF_LIMIT);
+ /*
+ * The limit is in 64-bit words. The encoder finishes a 64-byte burst
+ * it has started (measured on the RK3026), so give it whole bursts.
+ */
+ vepu_write_relaxed(vpu, round_down(size_left, 64) / 8,
+ H1_REG_STR_BUF_LIMIT);
if (pix_fmt->num_planes == 1) {
src[0] = vb2_dma_contig_plane_dma_addr(src_buf, 0);
--
2.53.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v2 3/3] media: verisilicon: leave room for the JPEG header and one stream burst
2026-11-10 12:41 [PATCH v2 0/3] media: verisilicon: fix VEPU1 JPEG encoder writes past the CAPTURE buffer Sergei Khomenkov via B4 Relay
2026-11-10 12:41 ` [PATCH v2 1/3] media: verisilicon: stop the VEPU1 JPEG encoder after an unfinished frame Sergei Khomenkov via B4 Relay
2026-11-10 12:41 ` [PATCH v2 2/3] media: verisilicon: program the H1 JPEG stream limit in 64-bit words Sergei Khomenkov via B4 Relay
@ 2026-11-10 12:41 ` Sergei Khomenkov via B4 Relay
2 siblings, 0 replies; 4+ messages in thread
From: Sergei Khomenkov via B4 Relay @ 2026-11-10 12:41 UTC (permalink / raw)
To: Nicolas Dufresne, Benjamin Gaignard, Philipp Zabel
Cc: Mauro Carvalho Chehab, Hans Verkuil, Heiko Stuebner,
Ezequiel Garcia, Chen-Yu Tsai, Hugues Fruchet, linux-media,
linux-rockchip, linux-arm-kernel, linux-stm32, linux-kernel,
stable, Sergei Khomenkov
From: Sergei Khomenkov <shomenkow@gmail.com>
hantro_try_fmt() keeps any non-zero CAPTURE sizeimage of the JPEG
encoder, however small. The CPU writes the 624-byte header into the
plane, and on the RK3026 VEPU1 the encoder then writes at least one
64-byte burst even with a stream limit of 0, so a smaller plane is
written past its end. A plane smaller than the header also makes the
WARN_ON() in hantro_h1_jpeg_enc_set_buffers() fire on every job.
Raise a smaller request to header_size + 64.
Found with an LLM coding assistant while porting mainline Linux to a
Rockchip RK3026 board; the assistant also drafted this change. Tested
on that board: a sizeimage of 1 or 600 now reads back 688, and frames
that do not fit a 688-byte plane stop exactly at its end. Not tested on
other SoCs.
Fixes: 775fec69008d ("media: add Rockchip VPU JPEG encoder driver")
Cc: stable@vger.kernel.org
Signed-off-by: Sergei Khomenkov <shomenkow@gmail.com>
---
drivers/media/platform/verisilicon/hantro_v4l2.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/media/platform/verisilicon/hantro_v4l2.c b/drivers/media/platform/verisilicon/hantro_v4l2.c
index 83af9fa1ce94..6a6d27443a5e 100644
--- a/drivers/media/platform/verisilicon/hantro_v4l2.c
+++ b/drivers/media/platform/verisilicon/hantro_v4l2.c
@@ -394,6 +394,15 @@ static int hantro_try_fmt(const struct hantro_ctx *ctx,
*/
pix_mp->plane_fmt[0].sizeimage = fmt->header_size +
pix_mp->width * pix_mp->height * fmt->max_depth;
+ } else if (fmt->codec_mode == HANTRO_MODE_JPEG_ENC) {
+ /*
+ * Room for the header and one stream burst (64 bytes on the
+ * RK3026 VEPU1), which the encoder writes even with a stream
+ * limit of 0.
+ */
+ pix_mp->plane_fmt[0].sizeimage =
+ max_t(u32, pix_mp->plane_fmt[0].sizeimage,
+ fmt->header_size + 64);
}
return 0;
--
2.53.0
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-11-10 12:41 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-10 12:41 [PATCH v2 0/3] media: verisilicon: fix VEPU1 JPEG encoder writes past the CAPTURE buffer Sergei Khomenkov via B4 Relay
2026-11-10 12:41 ` [PATCH v2 1/3] media: verisilicon: stop the VEPU1 JPEG encoder after an unfinished frame Sergei Khomenkov via B4 Relay
2026-11-10 12:41 ` [PATCH v2 2/3] media: verisilicon: program the H1 JPEG stream limit in 64-bit words Sergei Khomenkov via B4 Relay
2026-11-10 12:41 ` [PATCH v2 3/3] media: verisilicon: leave room for the JPEG header and one stream burst Sergei Khomenkov via B4 Relay
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®