From: Philipp Zabel
Date: Fri, 19 Nov 2021 10:41:20 +0000 (+0100)
Subject: media: coda: fix CODA960 JPEG encoder buffer overflow
X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=1a59cd88f55068710f6549bee548846661673780;p=linux.git
media: coda: fix CODA960 JPEG encoder buffer overflow
Stop the CODA960 JPEG encoder from overflowing capture buffers.
The bitstream buffer overflow interrupt doesn't seem to be connected,
so this has to be handled via timeout instead.
Reported-by: Martin Weber
Fixes: 96f6f62c4656 ("media: coda: jpeg: add CODA960 JPEG encoder support")
Tested-by: Martin Weber
Signed-off-by: Philipp Zabel
Signed-off-by: Hans Verkuil
Signed-off-by: Mauro Carvalho Chehab
---
diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
index 3cfd4368e9a90..3cd47ba26357e 100644
--- a/drivers/media/platform/coda/coda-common.c
+++ b/drivers/media/platform/coda/coda-common.c
@@ -1543,11 +1543,13 @@ static void coda_pic_run_work(struct work_struct *work)
if (!wait_for_completion_timeout(&ctx->completion,
msecs_to_jiffies(1000))) {
- dev_err(dev->dev, "CODA PIC_RUN timeout\n");
+ if (ctx->use_bit) {
+ dev_err(dev->dev, "CODA PIC_RUN timeout\n");
- ctx->hold = true;
+ ctx->hold = true;
- coda_hw_reset(ctx);
+ coda_hw_reset(ctx);
+ }
if (ctx->ops->run_timeout)
ctx->ops->run_timeout(ctx);
diff --git a/drivers/media/platform/coda/coda-jpeg.c b/drivers/media/platform/coda/coda-jpeg.c
index b11cfbe166dd3..a72f4655e5ad5 100644
--- a/drivers/media/platform/coda/coda-jpeg.c
+++ b/drivers/media/platform/coda/coda-jpeg.c
@@ -1127,7 +1127,8 @@ static int coda9_jpeg_prepare_encode(struct coda_ctx *ctx)
coda_write(dev, 0, CODA9_REG_JPEG_GBU_BT_PTR);
coda_write(dev, 0, CODA9_REG_JPEG_GBU_WD_PTR);
coda_write(dev, 0, CODA9_REG_JPEG_GBU_BBSR);
- coda_write(dev, 0, CODA9_REG_JPEG_BBC_STRM_CTRL);
+ coda_write(dev, BIT(31) | ((end_addr - start_addr - header_len) / 256),
+ CODA9_REG_JPEG_BBC_STRM_CTRL);
coda_write(dev, 0, CODA9_REG_JPEG_GBU_CTRL);
coda_write(dev, 0, CODA9_REG_JPEG_GBU_FF_RPTR);
coda_write(dev, 127, CODA9_REG_JPEG_GBU_BBER);
@@ -1257,6 +1258,23 @@ static void coda9_jpeg_finish_encode(struct coda_ctx *ctx)
coda_hw_reset(ctx);
}
+static void coda9_jpeg_encode_timeout(struct coda_ctx *ctx)
+{
+ struct coda_dev *dev = ctx->dev;
+ u32 end_addr, wr_ptr;
+
+ /* Handle missing BBC overflow interrupt via timeout */
+ end_addr = coda_read(dev, CODA9_REG_JPEG_BBC_END_ADDR);
+ wr_ptr = coda_read(dev, CODA9_REG_JPEG_BBC_WR_PTR);
+ if (wr_ptr >= end_addr - 256) {
+ v4l2_err(&dev->v4l2_dev, "JPEG too large for capture buffer\n");
+ coda9_jpeg_finish_encode(ctx);
+ return;
+ }
+
+ coda_hw_reset(ctx);
+}
+
static void coda9_jpeg_release(struct coda_ctx *ctx)
{
int i;
@@ -1276,6 +1294,7 @@ const struct coda_context_ops coda9_jpeg_encode_ops = {
.start_streaming = coda9_jpeg_start_encoding,
.prepare_run = coda9_jpeg_prepare_encode,
.finish_run = coda9_jpeg_finish_encode,
+ .run_timeout = coda9_jpeg_encode_timeout,
.release = coda9_jpeg_release,
};